aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--HOWTO/INSTALL-WIN32.md981
-rw-r--r--bootstrap/lib/compiler/ebin/beam_a.beambin2684 -> 2684 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_asm.beambin11456 -> 11524 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_bs.beambin5928 -> 5928 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_dict.beambin5248 -> 5292 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_disasm.beambin26216 -> 26216 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_validator.beambin30160 -> 29988 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/cerl_trees.beambin20360 -> 20360 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/compile.beambin38984 -> 38776 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/rec_env.beambin4720 -> 4920 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/sys_core_dsetel.beambin7308 -> 7184 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/sys_core_fold.beambin49728 -> 49728 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/sys_pre_expand.beambin14764 -> 13472 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/v3_kernel.beambin46896 -> 46856 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/code_server.beambin28688 -> 28852 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/erts_debug.beambin5452 -> 5548 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/file_io_server.beambin15184 -> 15564 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/global.beambin32348 -> 32252 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet.beambin23072 -> 23320 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet_db.beambin26652 -> 27044 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/user.beambin11572 -> 11572 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/beam_lib.beambin18532 -> 18520 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/epp.beambin28004 -> 26952 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_lint.beambin89268 -> 89380 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_pp.beambin26956 -> 26796 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/io.beambin6680 -> 6284 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/otp_internal.beambin11656 -> 11696 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/rand.beambin13444 -> 13440 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/random.beambin1704 -> 1736 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/shell.beambin30272 -> 30172 bytes
-rw-r--r--configure.in4
-rw-r--r--erts/aclocal.m414
-rw-r--r--erts/configure.in29
-rw-r--r--erts/doc/src/absform.xml923
-rw-r--r--erts/doc/src/erl.xml21
-rw-r--r--erts/doc/src/erl_driver.xml4
-rw-r--r--erts/doc/src/erl_nif.xml4
-rw-r--r--erts/doc/src/erl_prim_loader.xml35
-rw-r--r--erts/doc/src/erlang.xml136
-rw-r--r--erts/doc/src/init.xml5
-rw-r--r--erts/doc/src/notes.xml38
-rw-r--r--erts/emulator/beam/atom.h1
-rw-r--r--erts/emulator/beam/atom.names4
-rw-r--r--erts/emulator/beam/beam_bif_load.c392
-rw-r--r--erts/emulator/beam/beam_bp.c30
-rw-r--r--erts/emulator/beam/beam_debug.c42
-rw-r--r--erts/emulator/beam/beam_emu.c279
-rw-r--r--erts/emulator/beam/beam_load.c499
-rw-r--r--erts/emulator/beam/beam_load.h126
-rw-r--r--erts/emulator/beam/beam_ranges.c50
-rw-r--r--erts/emulator/beam/bif.c56
-rw-r--r--erts/emulator/beam/bif.h48
-rw-r--r--erts/emulator/beam/bif.tab15
-rw-r--r--erts/emulator/beam/binary.c81
-rw-r--r--erts/emulator/beam/break.c34
-rw-r--r--erts/emulator/beam/copy.c1284
-rw-r--r--erts/emulator/beam/dist.c98
-rw-r--r--erts/emulator/beam/erl_alloc.c193
-rw-r--r--erts/emulator/beam/erl_alloc.h34
-rw-r--r--erts/emulator/beam/erl_alloc.types10
-rw-r--r--erts/emulator/beam/erl_alloc_util.c375
-rw-r--r--erts/emulator/beam/erl_alloc_util.h68
-rw-r--r--erts/emulator/beam/erl_ao_firstfit_alloc.c22
-rw-r--r--erts/emulator/beam/erl_bif_binary.c4
-rw-r--r--erts/emulator/beam/erl_bif_ddll.c17
-rw-r--r--erts/emulator/beam/erl_bif_info.c317
-rw-r--r--erts/emulator/beam/erl_bif_trace.c26
-rw-r--r--erts/emulator/beam/erl_db.c4
-rw-r--r--erts/emulator/beam/erl_db_util.c12
-rw-r--r--erts/emulator/beam/erl_debug.c6
-rw-r--r--erts/emulator/beam/erl_debug.h1
-rw-r--r--erts/emulator/beam/erl_driver.h4
-rw-r--r--erts/emulator/beam/erl_gc.c1310
-rw-r--r--erts/emulator/beam/erl_gc.h38
-rw-r--r--erts/emulator/beam/erl_hl_timer.c85
-rw-r--r--erts/emulator/beam/erl_init.c35
-rw-r--r--erts/emulator/beam/erl_map.c96
-rw-r--r--erts/emulator/beam/erl_map.h13
-rw-r--r--erts/emulator/beam/erl_message.c1692
-rw-r--r--erts/emulator/beam/erl_message.h286
-rw-r--r--erts/emulator/beam/erl_nif.c34
-rw-r--r--erts/emulator/beam/erl_nif.h4
-rw-r--r--erts/emulator/beam/erl_nif_api_funcs.h2
-rw-r--r--erts/emulator/beam/erl_node_tables.c223
-rw-r--r--erts/emulator/beam/erl_process.c440
-rw-r--r--erts/emulator/beam/erl_process.h141
-rw-r--r--erts/emulator/beam/erl_process_dict.c72
-rw-r--r--erts/emulator/beam/erl_process_dict.h1
-rw-r--r--erts/emulator/beam/erl_process_dump.c13
-rw-r--r--erts/emulator/beam/erl_term.c31
-rw-r--r--erts/emulator/beam/erl_term.h44
-rw-r--r--erts/emulator/beam/erl_time_sup.c7
-rw-r--r--erts/emulator/beam/erl_trace.c74
-rw-r--r--erts/emulator/beam/external.c76
-rw-r--r--erts/emulator/beam/global.h297
-rw-r--r--erts/emulator/beam/hash.c112
-rw-r--r--erts/emulator/beam/hash.h11
-rw-r--r--erts/emulator/beam/io.c121
-rw-r--r--erts/emulator/beam/module.c4
-rw-r--r--erts/emulator/beam/module.h2
-rw-r--r--erts/emulator/beam/ops.tab3
-rw-r--r--erts/emulator/beam/sys.h44
-rw-r--r--erts/emulator/beam/utils.c45
-rw-r--r--erts/emulator/drivers/common/efile_drv.c1
-rw-r--r--erts/emulator/drivers/common/inet_drv.c9
-rw-r--r--erts/emulator/hipe/hipe_bif0.c12
-rw-r--r--erts/emulator/hipe/hipe_gc.c36
-rw-r--r--erts/emulator/hipe/hipe_mode_switch.c2
-rw-r--r--erts/emulator/hipe/hipe_mode_switch.h2
-rw-r--r--erts/emulator/hipe/hipe_native_bif.c36
-rw-r--r--erts/emulator/hipe/hipe_x86_signal.c31
-rw-r--r--erts/emulator/sys/common/erl_mmap.c575
-rw-r--r--erts/emulator/sys/common/erl_mmap.h30
-rw-r--r--erts/emulator/sys/common/erl_mseg.c11
-rw-r--r--erts/emulator/sys/common/erl_mseg.h16
-rw-r--r--erts/emulator/sys/common/erl_poll.h2
-rw-r--r--erts/emulator/sys/win32/erl_win32_sys_ddll.c3
-rw-r--r--erts/emulator/sys/win32/erl_win_dyn_driver.h4
-rw-r--r--erts/emulator/test/Makefile1
-rw-r--r--erts/emulator/test/alloc_SUITE.erl251
-rw-r--r--erts/emulator/test/alloc_SUITE_data/Makefile.src3
-rw-r--r--erts/emulator/test/alloc_SUITE_data/allocator_test.h20
-rw-r--r--erts/emulator/test/alloc_SUITE_data/basic.c3
-rw-r--r--erts/emulator/test/alloc_SUITE_data/basic.erl10
-rw-r--r--erts/emulator/test/alloc_SUITE_data/bucket_index.c2
-rw-r--r--erts/emulator/test/alloc_SUITE_data/bucket_index.erl10
-rw-r--r--erts/emulator/test/alloc_SUITE_data/bucket_mask.c4
-rw-r--r--erts/emulator/test/alloc_SUITE_data/bucket_mask.erl10
-rw-r--r--erts/emulator/test/alloc_SUITE_data/coalesce.c3
-rw-r--r--erts/emulator/test/alloc_SUITE_data/coalesce.erl10
-rw-r--r--erts/emulator/test/alloc_SUITE_data/cpool.c9
-rw-r--r--erts/emulator/test/alloc_SUITE_data/cpool.erl10
-rw-r--r--erts/emulator/test/alloc_SUITE_data/migration.c343
-rw-r--r--erts/emulator/test/alloc_SUITE_data/migration.erl10
-rw-r--r--erts/emulator/test/alloc_SUITE_data/mseg_clear_cache.c3
-rw-r--r--erts/emulator/test/alloc_SUITE_data/mseg_clear_cache.erl10
-rw-r--r--erts/emulator/test/alloc_SUITE_data/rbtree.c14
-rw-r--r--erts/emulator/test/alloc_SUITE_data/rbtree.erl10
-rw-r--r--erts/emulator/test/alloc_SUITE_data/realloc_copy.c2
-rw-r--r--erts/emulator/test/alloc_SUITE_data/realloc_copy.erl10
-rw-r--r--erts/emulator/test/alloc_SUITE_data/testcase_driver.c255
-rw-r--r--erts/emulator/test/alloc_SUITE_data/testcase_driver.h15
-rw-r--r--erts/emulator/test/alloc_SUITE_data/threads.c6
-rw-r--r--erts/emulator/test/alloc_SUITE_data/threads.erl10
-rw-r--r--erts/emulator/test/binary_SUITE.erl39
-rw-r--r--erts/emulator/test/bs_bincomp_SUITE.erl2
-rw-r--r--erts/emulator/test/code_SUITE.erl82
-rw-r--r--erts/emulator/test/code_SUITE_data/literals.erl7
-rw-r--r--erts/emulator/test/decode_packet_SUITE.erl47
-rw-r--r--erts/emulator/test/distribution_SUITE_data/run.erl47
-rw-r--r--erts/emulator/test/driver_SUITE.erl15
-rw-r--r--erts/emulator/test/erts_debug_SUITE.erl45
-rw-r--r--erts/emulator/test/evil_SUITE.erl4
-rw-r--r--erts/emulator/test/hash_SUITE.erl10
-rw-r--r--erts/emulator/test/map_SUITE.erl248
-rw-r--r--erts/emulator/test/message_queue_data_SUITE.erl239
-rw-r--r--erts/emulator/test/nif_SUITE.erl19
-rw-r--r--erts/emulator/test/nif_SUITE_data/nif_mod.c2
-rw-r--r--erts/emulator/test/op_SUITE.erl23
-rw-r--r--erts/emulator/test/port_SUITE.erl15
-rw-r--r--erts/emulator/test/port_bif_SUITE.erl9
-rw-r--r--erts/emulator/test/random_iolist.erl16
-rw-r--r--erts/emulator/test/save_calls_SUITE.erl4
-rw-r--r--erts/emulator/test/system_profile_SUITE.erl2
-rw-r--r--erts/emulator/test/time_SUITE.erl36
-rw-r--r--erts/emulator/test/trace_SUITE.erl4
-rw-r--r--erts/epmd/src/epmd.c2
-rw-r--r--erts/etc/common/ct_run.c25
-rw-r--r--erts/etc/common/dialyzer.c24
-rw-r--r--erts/etc/common/erlc.c22
-rw-r--r--erts/etc/common/erlexec.c25
-rw-r--r--erts/etc/common/escript.c25
-rw-r--r--erts/etc/common/heart.c2
-rw-r--r--erts/etc/common/typer.c26
-rw-r--r--erts/include/internal/ethread.h3
-rw-r--r--erts/preloaded/ebin/erl_prim_loader.beambin56328 -> 56060 bytes
-rw-r--r--erts/preloaded/ebin/erlang.beambin101840 -> 101752 bytes
-rw-r--r--erts/preloaded/ebin/erts_internal.beambin5964 -> 6076 bytes
-rw-r--r--erts/preloaded/ebin/init.beambin48768 -> 48600 bytes
-rw-r--r--erts/preloaded/ebin/otp_ring0.beambin1468 -> 1460 bytes
-rw-r--r--erts/preloaded/ebin/prim_eval.beambin1340 -> 1332 bytes
-rw-r--r--erts/preloaded/ebin/prim_file.beambin44904 -> 44788 bytes
-rw-r--r--erts/preloaded/ebin/prim_inet.beambin72628 -> 72624 bytes
-rw-r--r--erts/preloaded/ebin/prim_zip.beambin23416 -> 23296 bytes
-rw-r--r--erts/preloaded/ebin/zlib.beambin14176 -> 14168 bytes
-rw-r--r--erts/preloaded/src/erlang.erl56
-rw-r--r--erts/preloaded/src/erts_internal.erl20
-rw-r--r--erts/preloaded/src/init.erl2
-rw-r--r--erts/preloaded/src/prim_inet.erl4
-rw-r--r--erts/test/ethread_SUITE.erl32
-rw-r--r--erts/test/run_erl_SUITE.erl18
-rw-r--r--lib/asn1/src/asn1ct_value.erl5
-rw-r--r--lib/asn1/src/asn1rtt_ber.erl4
-rw-r--r--lib/asn1/test/testPrimStrings.erl11
-rw-r--r--lib/common_test/doc/src/ct_hooks_chapter.xml20
-rw-r--r--lib/common_test/doc/src/event_handler_chapter.xml5
-rw-r--r--lib/common_test/doc/src/notes.xml21
-rw-r--r--lib/common_test/doc/src/run_test_chapter.xml16
-rw-r--r--lib/common_test/src/ct_config.erl3
-rw-r--r--lib/common_test/src/ct_conn_log_h.erl27
-rw-r--r--lib/common_test/src/ct_netconfc.erl75
-rw-r--r--lib/common_test/src/ct_run.erl20
-rw-r--r--lib/common_test/src/ct_slave.erl10
-rw-r--r--lib/common_test/src/ct_snmp.erl18
-rw-r--r--lib/common_test/src/ct_telnet.erl12
-rw-r--r--lib/common_test/test/ct_master_SUITE.erl2
-rw-r--r--lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl47
-rw-r--r--lib/common_test/test/ct_netconfc_SUITE_data/ns.erl17
-rw-r--r--lib/common_test/test/ct_test_support.erl8
-rw-r--r--lib/compiler/doc/src/notes.xml26
-rw-r--r--lib/compiler/src/beam_asm.erl5
-rw-r--r--lib/compiler/src/beam_dict.erl11
-rw-r--r--lib/compiler/src/beam_validator.erl26
-rw-r--r--lib/compiler/src/cerl_trees.erl4
-rw-r--r--lib/compiler/src/compile.erl11
-rw-r--r--lib/compiler/src/rec_env.erl11
-rw-r--r--lib/compiler/src/sys_core_dsetel.erl36
-rw-r--r--lib/compiler/src/sys_core_fold.erl6
-rw-r--r--lib/compiler/src/sys_pre_expand.erl179
-rw-r--r--lib/compiler/src/v3_kernel.erl17
-rw-r--r--lib/compiler/test/bs_match_SUITE.erl38
-rw-r--r--lib/compiler/test/map_SUITE.erl22
-rw-r--r--lib/compiler/test/match_SUITE.erl7
-rw-r--r--lib/compiler/test/misc_SUITE.erl10
-rw-r--r--lib/crypto/c_src/crypto.c2554
-rw-r--r--lib/crypto/c_src/crypto_callback.c4
-rw-r--r--lib/crypto/doc/src/crypto.xml91
-rw-r--r--lib/crypto/src/crypto.erl849
-rw-r--r--lib/debugger/src/dbg_iload.erl2
-rw-r--r--lib/debugger/test/map_SUITE.erl22
-rw-r--r--lib/dialyzer/src/dialyzer_contracts.erl18
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/results/mnesia2
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/contracts_with_subtypes36
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/contracts_with_subtypes22
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/pretty_bitstring2
-rw-r--r--lib/dialyzer/test/user_SUITE_data/results/wsp_pdu2
-rw-r--r--lib/diameter/src/base/diameter_traffic.erl77
-rw-r--r--lib/diameter/src/diameter.appup.src6
-rw-r--r--lib/diameter/vsn.mk2
-rw-r--r--lib/erl_docgen/priv/dtd/cites.dtd2
-rw-r--r--lib/erl_docgen/priv/dtd/common.dtd24
-rw-r--r--lib/erl_docgen/priv/dtd/common.header.dtd4
-rw-r--r--lib/erl_docgen/priv/dtd/common.refs.dtd18
-rw-r--r--lib/erl_docgen/priv/dtd/erlref.dtd3
-rw-r--r--lib/erl_docgen/priv/dtd/terms.dtd2
-rw-r--r--lib/erl_docgen/priv/xsl/db_html.xsl5
-rw-r--r--lib/erl_docgen/priv/xsl/db_man.xsl6
-rw-r--r--lib/erl_docgen/priv/xsl/db_pdf.xsl6
-rw-r--r--lib/erl_docgen/src/docgen_edoc_xml_cb.erl24
-rw-r--r--lib/erl_docgen/vsn.mk2
-rw-r--r--lib/erl_interface/src/connect/ei_resolve.c14
-rw-r--r--lib/eunit/doc/overview.edoc2
-rw-r--r--lib/eunit/include/eunit.hrl1
-rw-r--r--lib/gs/Makefile2
-rw-r--r--lib/gs/contribs/Makefile32
-rw-r--r--lib/gs/contribs/bonk/Makefile109
-rw-r--r--lib/gs/contribs/bonk/bitmaps/bonkbomb66
-rw-r--r--lib/gs/contribs/bonk/bitmaps/bonkface66
-rw-r--r--lib/gs/contribs/bonk/bitmaps/bonklogo320
-rw-r--r--lib/gs/contribs/bonk/bitmaps/bonkmiss66
-rw-r--r--lib/gs/contribs/bonk/bitmaps/bonktom66
-rw-r--r--lib/gs/contribs/bonk/bitmaps/bonkx66
-rw-r--r--lib/gs/contribs/bonk/bitmaps/erl-e106
-rw-r--r--lib/gs/contribs/bonk/bitmaps/erl-text106
-rw-r--r--lib/gs/contribs/bonk/bonk.erl584
-rw-r--r--lib/gs/contribs/bonk/bonk.gifbin196 -> 0 bytes
-rw-r--r--lib/gs/contribs/bonk/bonk.tool6
-rw-r--r--lib/gs/contribs/bonk/bonk.txt30
-rw-r--r--lib/gs/contribs/bonk/bonk_sound.erl82
-rw-r--r--lib/gs/contribs/bonk/bonk_square.erl146
-rw-r--r--lib/gs/contribs/bonk/sounder.erl160
-rw-r--r--lib/gs/contribs/bonk/sounds/bonk.aubin2008 -> 0 bytes
-rw-r--r--lib/gs/contribs/bonk/sounds/damn.aubin3744 -> 0 bytes
-rw-r--r--lib/gs/contribs/bonk/sounds/explosion.aubin7708 -> 0 bytes
-rw-r--r--lib/gs/contribs/bonk/sounds/gameover.aubin5986 -> 0 bytes
-rw-r--r--lib/gs/contribs/bonk/sounds/hehee.aubin3772 -> 0 bytes
-rw-r--r--lib/gs/contribs/bonk/sounds/level.aubin5360 -> 0 bytes
-rw-r--r--lib/gs/contribs/bonk/sounds/missedme.aubin2735 -> 0 bytes
-rw-r--r--lib/gs/contribs/bonk/sounds/music.aubin48072 -> 0 bytes
-rw-r--r--lib/gs/contribs/bonk/sounds/ouch!!!.aubin2342 -> 0 bytes
-rw-r--r--lib/gs/contribs/bonk/sounds/praisejesus.aubin16730 -> 0 bytes
-rw-r--r--lib/gs/contribs/bonk/sounds/trumpet.aubin49332 -> 0 bytes
-rw-r--r--lib/gs/contribs/bonk/sounds/yes.aubin4400 -> 0 bytes
-rw-r--r--lib/gs/contribs/cols/Makefile103
-rw-r--r--lib/gs/contribs/cols/cols.erl625
-rw-r--r--lib/gs/contribs/cols/cols.gifbin185 -> 0 bytes
-rw-r--r--lib/gs/contribs/cols/cols.tool5
-rw-r--r--lib/gs/contribs/cols/help.gifbin172 -> 0 bytes
-rw-r--r--lib/gs/contribs/cols/highscore.erl103
-rw-r--r--lib/gs/contribs/ebin/.gitignore0
-rw-r--r--lib/gs/contribs/mandel/Makefile101
-rw-r--r--lib/gs/contribs/mandel/mandel.erl351
-rw-r--r--lib/gs/contribs/mandel/mandel.gifbin394 -> 0 bytes
-rw-r--r--lib/gs/contribs/mandel/mandel.html74
-rw-r--r--lib/gs/contribs/mandel/mandel.tool6
-rw-r--r--lib/gs/contribs/othello/Makefile101
-rw-r--r--lib/gs/contribs/othello/othello.erl237
-rw-r--r--lib/gs/contribs/othello/othello.gifbin148 -> 0 bytes
-rw-r--r--lib/gs/contribs/othello/othello.tool6
-rw-r--r--lib/gs/contribs/othello/othello_adt.erl540
-rw-r--r--lib/gs/contribs/othello/othello_board.erl649
-rw-r--r--lib/gs/contribs/othello/priv/marker.bm43
-rw-r--r--lib/gs/contribs/othello/priv/square.bm43
-rw-r--r--lib/hipe/cerl/erl_types.erl105
-rw-r--r--lib/hipe/icode/hipe_icode.erl6
-rw-r--r--lib/hipe/rtl/Makefile2
-rw-r--r--lib/hipe/rtl/hipe_rtl_binary_match.erl104
-rw-r--r--lib/hipe/rtl/hipe_tagscheme.erl30
-rw-r--r--lib/hipe/test/bs_SUITE_data/bs_match.erl108
-rw-r--r--lib/inets/doc/src/http_server.xml31
-rw-r--r--lib/inets/doc/src/http_uri.xml10
-rw-r--r--lib/inets/doc/src/httpc.xml10
-rw-r--r--lib/inets/doc/src/httpd.xml254
-rw-r--r--lib/inets/doc/src/notes.xml99
-rw-r--r--lib/inets/doc/src/tftp.xml21
-rw-r--r--lib/inets/src/http_client/httpc_handler.erl85
-rw-r--r--lib/inets/src/http_lib/http_chunk.erl184
-rw-r--r--lib/inets/src/http_lib/http_response.erl2
-rw-r--r--lib/inets/src/http_lib/http_transport.erl206
-rw-r--r--lib/inets/src/http_lib/http_util.erl69
-rw-r--r--lib/inets/src/http_server/Makefile2
-rw-r--r--lib/inets/src/http_server/httpd_conf.erl101
-rw-r--r--lib/inets/src/http_server/httpd_custom_api.erl3
-rw-r--r--lib/inets/src/http_server/httpd_example.erl10
-rw-r--r--lib/inets/src/http_server/httpd_request_handler.erl25
-rw-r--r--lib/inets/src/http_server/httpd_response.erl27
-rw-r--r--lib/inets/src/http_server/httpd_sup.erl4
-rw-r--r--lib/inets/src/http_server/httpd_util.erl28
-rw-r--r--lib/inets/src/http_server/mod_esi.erl47
-rw-r--r--lib/inets/src/inets_app/inets.app.src1
-rw-r--r--lib/inets/test/http_format_SUITE.erl238
-rw-r--r--lib/inets/test/httpc_SUITE.erl76
-rw-r--r--lib/inets/test/httpd_1_1.erl11
-rw-r--r--lib/inets/test/httpd_SUITE.erl33
-rw-r--r--lib/inets/test/httpd_SUITE_data/Makefile.src5
-rw-r--r--lib/inets/test/httpd_test_lib.erl16
-rw-r--r--lib/inets/vsn.mk2
-rw-r--r--lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangMap.java23
-rw-r--r--lib/jinterface/java_src/com/ericsson/otp/erlang/OtpInputStream.java3
-rw-r--r--lib/jinterface/java_src/com/ericsson/otp/erlang/OtpOutputStream.java23
-rw-r--r--lib/jinterface/test/nc_SUITE.erl2
-rw-r--r--lib/kernel/doc/src/code.xml6
-rw-r--r--lib/kernel/doc/src/file.xml4
-rw-r--r--lib/kernel/doc/src/notes.xml16
-rw-r--r--lib/kernel/src/code_server.erl25
-rw-r--r--lib/kernel/src/erts_debug.erl17
-rw-r--r--lib/kernel/src/file_io_server.erl122
-rw-r--r--lib/kernel/src/global.erl20
-rw-r--r--lib/kernel/src/inet.erl14
-rw-r--r--lib/kernel/test/file_SUITE.erl64
-rw-r--r--lib/kernel/test/file_name_SUITE.erl6
-rw-r--r--lib/kernel/test/gen_tcp_echo_SUITE.erl9
-rw-r--r--lib/kernel/test/global_SUITE.erl2
-rw-r--r--lib/kernel/test/inet_SUITE.erl3
-rw-r--r--lib/kernel/test/inet_res_SUITE.erl2
-rw-r--r--lib/kernel/test/inet_sockopt_SUITE.erl82
-rw-r--r--lib/kernel/test/zlib_SUITE.erl6
-rw-r--r--lib/mnesia/src/mnesia_lib.erl15
-rw-r--r--lib/mnesia/test/mnesia_consistency_test.erl2
-rw-r--r--lib/observer/doc/src/crashdump_ug.xml2
-rw-r--r--lib/observer/doc/src/notes.xml12
-rw-r--r--lib/observer/doc/src/observer_ug.xml3
-rw-r--r--lib/observer/doc/src/ttb.xml17
-rw-r--r--lib/observer/doc/src/ttb_ug.xml7
-rw-r--r--lib/observer/src/observer_html_lib.erl4
-rw-r--r--lib/orber/doc/src/notes.xml6
-rw-r--r--lib/percept/test/egd_SUITE.erl4
-rw-r--r--lib/public_key/asn1/PKIX1Explicit88.asn1109
-rw-r--r--lib/public_key/vsn.mk2
-rw-r--r--lib/reltool/src/reltool_fgraph_win.erl4
-rw-r--r--lib/sasl/doc/src/alarm_handler.xml84
-rw-r--r--lib/sasl/doc/src/appup.xml449
-rw-r--r--lib/sasl/doc/src/book.xml4
-rw-r--r--lib/sasl/doc/src/error_logging.xml215
-rw-r--r--lib/sasl/doc/src/overload.xml124
-rw-r--r--lib/sasl/doc/src/part.xml5
-rw-r--r--lib/sasl/doc/src/rb.xml285
-rw-r--r--lib/sasl/doc/src/ref_man.xml4
-rw-r--r--lib/sasl/doc/src/rel.xml91
-rw-r--r--lib/sasl/doc/src/release_handler.xml743
-rw-r--r--lib/sasl/doc/src/relup.xml70
-rw-r--r--lib/sasl/doc/src/sasl_app.xml178
-rw-r--r--lib/sasl/doc/src/sasl_intro.xml38
-rw-r--r--lib/sasl/doc/src/script.xml157
-rw-r--r--lib/sasl/doc/src/systools.xml347
-rw-r--r--lib/snmp/doc/src/snmp_agent_netif.xml3
-rw-r--r--lib/snmp/doc/src/snmp_app.xml276
-rw-r--r--lib/snmp/doc/src/snmp_config.xml280
-rw-r--r--lib/snmp/doc/src/snmp_manager_netif.xml3
-rw-r--r--lib/snmp/doc/src/snmpa.xml4
-rw-r--r--lib/snmp/doc/src/snmpm.xml8
-rw-r--r--lib/snmp/src/app/snmp.appup.src2
-rw-r--r--lib/snmp/src/misc/snmp_conf.erl2
-rw-r--r--lib/ssh/doc/src/notes.xml26
-rw-r--r--lib/ssh/doc/src/ssh.xml124
-rw-r--r--lib/ssh/doc/src/ssh_app.xml214
-rw-r--r--lib/ssh/doc/src/ssh_connection.xml20
-rw-r--r--lib/ssh/doc/src/ssh_server_key_api.xml4
-rw-r--r--lib/ssh/doc/src/ssh_sftp.xml31
-rw-r--r--lib/ssh/doc/src/using_ssh.xml6
-rw-r--r--lib/ssh/doc/standard/draft-ietf-secsh-architecture-15.2.ps3315
-rw-r--r--lib/ssh/doc/standard/draft-ietf-secsh-architecture-15.txt1624
-rw-r--r--lib/ssh/doc/standard/draft-ietf-secsh-connect-18.2.ps2557
-rw-r--r--lib/ssh/doc/standard/draft-ietf-secsh-connect-18.txt1232
-rw-r--r--lib/ssh/doc/standard/draft-ietf-secsh-filexfer-02.2.ps2853
-rw-r--r--lib/ssh/doc/standard/draft-ietf-secsh-filexfer-02.txt1627
-rw-r--r--lib/ssh/doc/standard/draft-ietf-secsh-filexfer-03.2.ps3511
-rw-r--r--lib/ssh/doc/standard/draft-ietf-secsh-filexfer-03.txt1962
-rw-r--r--lib/ssh/doc/standard/draft-ietf-secsh-filexfer-04.txt2130
-rw-r--r--lib/ssh/doc/standard/draft-ietf-secsh-transport-17.2.ps3205
-rw-r--r--lib/ssh/doc/standard/draft-ietf-secsh-transport-17.txt1624
-rw-r--r--lib/ssh/doc/standard/draft-ietf-secsh-userauth-18.2.ps1881
-rw-r--r--lib/ssh/doc/standard/draft-ietf-secsh-userauth-18.txt896
-rw-r--r--lib/ssh/src/ssh.erl111
-rw-r--r--lib/ssh/src/ssh.hrl4
-rw-r--r--lib/ssh/src/ssh_acceptor.erl7
-rw-r--r--lib/ssh/src/ssh_auth.erl13
-rw-r--r--lib/ssh/src/ssh_auth.hrl1
-rw-r--r--lib/ssh/src/ssh_connect.hrl3
-rw-r--r--lib/ssh/src/ssh_connection.erl4
-rw-r--r--lib/ssh/src/ssh_connection_handler.erl266
-rw-r--r--lib/ssh/src/ssh_file.erl30
-rw-r--r--lib/ssh/src/ssh_sftpd.erl22
-rw-r--r--lib/ssh/src/ssh_transport.erl615
-rw-r--r--lib/ssh/test/Makefile2
-rw-r--r--lib/ssh/test/ssh_algorithms_SUITE.erl7
-rw-r--r--lib/ssh/test/ssh_algorithms_SUITE_data/id_ecdsa5
-rw-r--r--lib/ssh/test/ssh_algorithms_SUITE_data/id_ecdsa.pub1
-rw-r--r--lib/ssh/test/ssh_algorithms_SUITE_data/id_ecdsa2565
-rw-r--r--lib/ssh/test/ssh_algorithms_SUITE_data/id_ecdsa256.pub1
-rw-r--r--lib/ssh/test/ssh_algorithms_SUITE_data/ssh_host_ecdsa_key2565
-rw-r--r--lib/ssh/test/ssh_algorithms_SUITE_data/ssh_host_ecdsa_key256.pub1
-rw-r--r--lib/ssh/test/ssh_basic_SUITE.erl239
-rw-r--r--lib/ssh/test/ssh_key_cb.erl45
-rw-r--r--lib/ssh/test/ssh_key_cb_options.erl44
-rw-r--r--lib/ssh/test/ssh_protocol_SUITE.erl51
-rw-r--r--lib/ssh/test/ssh_renegotiate_SUITE.erl40
-rw-r--r--lib/ssh/test/ssh_test_lib.erl22
-rw-r--r--lib/ssh/test/ssh_to_openssh_SUITE.erl88
-rw-r--r--lib/ssh/vsn.mk1
-rw-r--r--lib/ssl/doc/src/notes.xml23
-rw-r--r--lib/ssl/doc/src/ssl.xml45
-rw-r--r--lib/ssl/doc/src/ssl_app.xml46
-rw-r--r--lib/ssl/doc/src/ssl_crl_cache_api.xml6
-rw-r--r--lib/ssl/doc/src/ssl_session_cache_api.xml10
-rw-r--r--lib/ssl/src/dtls_connection.erl2
-rw-r--r--lib/ssl/src/inet_tls_dist.erl2
-rw-r--r--lib/ssl/src/ssl.app.src2
-rw-r--r--lib/ssl/src/ssl.appup.src14
-rw-r--r--lib/ssl/src/ssl.erl2
-rw-r--r--lib/ssl/src/ssl_connection.erl4
-rw-r--r--lib/ssl/src/ssl_dist_sup.erl2
-rw-r--r--lib/ssl/src/ssl_internal.hrl3
-rw-r--r--lib/ssl/src/ssl_manager.erl186
-rw-r--r--lib/ssl/src/ssl_session.erl11
-rw-r--r--lib/ssl/src/ssl_session_cache.erl8
-rw-r--r--lib/ssl/src/ssl_session_cache_api.erl1
-rw-r--r--lib/ssl/src/ssl_tls_dist_proxy.erl86
-rw-r--r--lib/ssl/src/ssl_v3.erl1
-rw-r--r--lib/ssl/src/tls_connection.erl5
-rw-r--r--lib/ssl/src/tls_record.erl62
-rw-r--r--lib/ssl/test/ssl_ECC_SUITE.erl20
-rw-r--r--lib/ssl/test/ssl_basic_SUITE.erl65
-rw-r--r--lib/ssl/test/ssl_dist_SUITE.erl149
-rw-r--r--lib/ssl/test/ssl_session_cache_SUITE.erl152
-rw-r--r--lib/ssl/test/ssl_test_lib.erl14
-rw-r--r--lib/ssl/test/ssl_to_openssl_SUITE.erl216
-rw-r--r--lib/ssl/vsn.mk2
-rw-r--r--lib/stdlib/doc/src/rand.xml2
-rw-r--r--lib/stdlib/doc/src/random.xml4
-rw-r--r--lib/stdlib/src/epp.erl326
-rw-r--r--lib/stdlib/src/erl_lint.erl32
-rw-r--r--lib/stdlib/src/erl_parse.yrl14
-rw-r--r--lib/stdlib/src/erl_pp.erl21
-rw-r--r--lib/stdlib/src/io.erl43
-rw-r--r--lib/stdlib/src/otp_internal.erl6
-rw-r--r--lib/stdlib/src/rand.erl2
-rw-r--r--lib/stdlib/src/random.erl1
-rw-r--r--lib/stdlib/src/shell.erl15
-rw-r--r--lib/stdlib/test/base64_SUITE.erl2
-rw-r--r--lib/stdlib/test/binary_module_SUITE.erl40
-rw-r--r--lib/stdlib/test/dict_SUITE.erl16
-rw-r--r--lib/stdlib/test/epp_SUITE.erl56
-rw-r--r--lib/stdlib/test/erl_lint_SUITE.erl74
-rw-r--r--lib/stdlib/test/erl_pp_SUITE.erl14
-rw-r--r--lib/stdlib/test/ets_SUITE.erl80
-rw-r--r--lib/stdlib/test/ets_tough_SUITE.erl10
-rw-r--r--lib/stdlib/test/filelib_SUITE.erl2
-rw-r--r--lib/stdlib/test/lists_SUITE.erl22
-rw-r--r--lib/stdlib/test/queue_SUITE.erl10
-rw-r--r--lib/stdlib/test/rand_SUITE.erl3
-rw-r--r--lib/stdlib/test/random_iolist.erl16
-rw-r--r--lib/stdlib/test/random_unicode_list.erl18
-rw-r--r--lib/stdlib/test/run_pcre_tests.erl10
-rw-r--r--lib/stdlib/test/select_SUITE.erl21
-rw-r--r--lib/stdlib/test/sets_SUITE.erl22
-rw-r--r--lib/stdlib/test/timer_SUITE.erl24
-rw-r--r--lib/syntax_tools/src/erl_syntax_lib.erl12
-rw-r--r--lib/test_server/src/test_server_ctrl.erl18
-rw-r--r--lib/test_server/src/test_server_node.erl3
-rw-r--r--lib/tools/src/make.erl10
-rw-r--r--lib/wx/api_gen/gl_gen_erl.erl12
-rw-r--r--lib/wx/api_gen/wx_extra/added_func.h6
-rw-r--r--lib/wx/api_gen/wx_extra/wxEvtHandler.c_src4
-rw-r--r--lib/wx/api_gen/wx_gen_cpp.erl6
-rw-r--r--lib/wx/api_gen/wxapi.conf10
-rw-r--r--lib/wx/c_src/gen/wxe_derived_dest.h10
-rw-r--r--lib/wx/c_src/gen/wxe_events.cpp5
-rw-r--r--lib/wx/c_src/gen/wxe_funcs.cpp77
-rw-r--r--lib/wx/c_src/gen/wxe_macros.h5010
-rw-r--r--lib/wx/c_src/wxe_helpers.cpp58
-rw-r--r--lib/wx/c_src/wxe_helpers.h4
-rw-r--r--lib/wx/c_src/wxe_impl.cpp101
-rw-r--r--lib/wx/c_src/wxe_impl.h4
-rw-r--r--lib/wx/examples/demo/ex_canvas.erl49
-rw-r--r--lib/wx/examples/sudoku/sudoku_game.erl7
-rw-r--r--lib/wx/src/gen/gl.erl72
-rw-r--r--lib/wx/src/gen/glu.erl8
-rw-r--r--lib/wx/src/gen/wxDCOverlay.erl70
-rw-r--r--lib/wx/src/gen/wxOverlay.erl57
-rw-r--r--lib/wx/src/gen/wxToolBar.erl36
-rw-r--r--lib/wx/src/gen/wxe_debug.hrl5009
-rw-r--r--lib/wx/src/gen/wxe_funcs.hrl5009
-rw-r--r--lib/wx/src/wxe_server.erl21
-rw-r--r--lib/wx/src/wxe_util.erl17
-rw-r--r--lib/wx/test/wx_class_SUITE.erl13
-rw-r--r--make/otp_release_targets.mk11
-rw-r--r--otp_versions.table4
-rw-r--r--system/doc/reference_manual/processes.xml4
-rw-r--r--system/doc/reference_manual/typespec.xml24
530 files changed, 25303 insertions, 53140 deletions
diff --git a/HOWTO/INSTALL-WIN32.md b/HOWTO/INSTALL-WIN32.md
index 79d89551c0..067c939d7a 100644
--- a/HOWTO/INSTALL-WIN32.md
+++ b/HOWTO/INSTALL-WIN32.md
@@ -4,82 +4,110 @@ How to Build Erlang/OTP on Windows
Introduction
------------
-This file describes how to build the Erlang emulator and the OTP
-libraries on Windows. The instructions apply to versions of Windows
-supporting the Cygwin emulated gnuish environment for Windows or the
-Msys ditto. We've built on the following platforms: Windows 2003
-server, Windows XP Home/Professional, Windows Vista and Windows 7 (32
-and 64 bit). You can probably build on Windows 2000, but you will not
-be able to install the latest Microsoft SDK, so you have to go back to
-some earlier compiler. Any Windows95'ish platform will surely get you
-into trouble, what I'm not sure of, but it certainly will...
-
-The procedure described uses either Cygwin or Msys as a build
-environment, you run the bash shell in Cygwin/Msys and use gnu
-make/configure/autoconf etc to do the build. The emulator C-source
-code is, however, mostly compiled with Microsoft Visual C++â„¢,
-producing a native Windows binary. This is the same procedure as we
-use to build the pre-built binaries. The fact that we use VC++ and not
-gcc is explained further in the FAQ section.
-
-I describe the build procedure to make it possible for open source
-customers to build the emulator, given that they have the needed
-tools. The binary Windows releases is still a preferred alternative if
-one does not have Microsoft's development tools and/or don't want to
-install Cygwin or Msys.
-
-To use Cygwin/Msys, one needs basic experience from a Unix environment, if
-one does not know how to set environment variables, run programs etc
-in a Unix environment, one will be quite lost in the Cygwin os Msys
-ditto. I can unfortunately not teach all the world how to use
-Cygwin and bash, neither how to install Cygwin nor perform basic tasks
-on a computer. Please refer to other documentation on the net for
-help, or use the binary release instead if you have problems using the
-tools.
-
-However, if you feel comfortable with the environment and build
+This section describes how to build the Erlang emulator and the OTP
+libraries on Windows. Note that the Windows binary releases are still
+a preferred alternative if one does not have Microsoft’s development
+tools and/or don’t want to install Cygwin, MSYS or MSYS2.
+
+The instructions apply to versions of Windows supporting the Cygwin
+emulated gnuish environment or the MSYS or MSYS2 ditto. We’ve built on
+the following platforms: Windows 2012, Windows 7, Windows 8 and Windows 10.
+It’s probably possible to build on older platforms too, but you might
+not be able to install the appropriate Microsoft SDK, Visual Studio or
+OpenSSL, in which case you will need to go back to earlier compilers etc.
+
+The procedure described uses either Cygwin, MSYS or MSYS2 as a build
+environment. You run the bash shell in Cygwin/MSYS/MSYS2 and use the gnu
+make/configure/autoconf etc to do the build. The emulator C-source code
+is, however, mostly compiled with Microsoft Visual C++â„¢, producing a
+native Windows binary. This is the same procedure as we use to build the
+pre-built binaries. Why we use VC++ and not gcc is explained further in
+the FAQ section.
+
+If you are not familiar with Cygwin, MSYS, MSYS2 or a Unix environment,
+you’ll probably need to read up a bit on how that works. There are plenty of
+documentation about this online.
+
+These instructions apply for both 32-bit and 64-bit Windows. Note that even
+if you build a 64-bit version of Erlang, most of the directories and files
+involved are still named win32. Some occurances of the name win64 are
+however present. The installation file for a 64-bit Windows version of
+Erlang, for example, is `otp_win64_%OTP-REL%.exe`.
+
+If you feel comfortable with the environment and build
system, and have all the necessary tools, you have a great opportunity
to make the Erlang/OTP distribution for Windows better. Please submit
-any suggestions and patches to the appropriate [mailing lists] [1] to let
+any suggestions to our [JIRA] [2] and patches to our [git project] [3] to let
them find their way into the next version of Erlang. If making changes
to the build system (like makefiles etc) please bear in mind that the
same makefiles are used on Unix/VxWorks, so that your changes
-don't break other platforms. That of course goes for C-code too, system
+don't break other platforms. That of course goes for C-code too; system
specific code resides in the `$ERL_TOP/erts/emulator/sys/win32` and
`$ERL_TOP/erts/etc/win32` directories mostly. The
`$ERL_TOP/erts/emulator/beam` directory is for common code.
-Before the R9C release of Erlang/OTP, the Windows release was built
-partly on a Unix (Solaris) box and partly on a Windows box, using Perl
-hacks to communicate and sync between the two machines. R9C was the
-first release ever built solely on Windows, where no Unix machine is
-needed at all. Now we've used this build procedure for a couple of
+We've used this build procedure for a couple of
releases, and it has worked fine for us. Still, there might be all
sorts of troubles on different machines and with different
-setups. I'll try to give hints wherever I've encountered difficulties,
+setups. We'll try to give hints wherever we've encountered difficulties,
but please share your experiences by using the [erlang-questions] [1]
-mailing list. I cannot of course help everyone with all
-their problems, please try to solve the problems and submit
-solutions/workarounds. Remember, it's all about sharing, not about
-demanding...
-
-Starting with R15B, our build system runs both on Cygwin and Msys
-(MinGW's fork of an early cygwin version). Msys is a smaller package
-to install and may on some machines run slightly faster. If Cygwin
-gives you trouble, try Msys instead, and v.v. Beginning with R15B
-there is also a native 64bit version of Erlang for 64bit Windows 7
-(only). These instructions apply to both the 32bit VM and the 64bit
-ditto.
-
-Note that even if you build a 64bit VM, most of the directories and
-files involved are still named win32. You can view the name win32 as
-meaning any windows version not beeing 16bit. A few occurences of the
-name Win64 are however present in the system, for example the
-installation file for a 64 bit windows version of Erlang is by default
-named `otp_win64_<version>.exe`.
-
-Lets go then, I'll start with a little FAQ, based on in house questions
-and misunderstandings.
+mailing list. We cannot, of course, help everyone with all
+their issues, so please try to solve such issues and submit
+solutions/workarounds.
+
+Lets go then! We’ll start with a short version of the setup procedure,
+followed by some FAQ, and then we’ll go into more details of the setup.
+
+
+Short Version
+--------------------------
+In the following sections, we've described as much as we could about the
+installation of the tools needed. Once the tools are installed, building
+is quite easy. We have also tried to make these instructions understandable
+for people with limited Unix experience. Cygwin/MSYS/MSYS2 is a whole new
+environment to some Windows users, why careful explanation of environment
+variables etc seemed to be in place.
+
+This is the short story though, for the experienced and impatient:
+
+ * Get and install complete Cygwin (latest), complete MinGW with MSYS or
+ complete MSYS2
+
+ * Install Visual Studio 12.0 (2013)
+
+ * Install Microsofts Windows SDK 8.1
+
+ * Get and install Sun's JDK 1.6.0 or later
+
+ * Get and install NSIS 2.01 or later (up to 2.46 tried and working)
+
+ * Get, build and install OpenSSL 0.9.8r or later (up to 1.0.2d
+ tried & working) with static libs.
+
+ * Get the Erlang source distribution (from
+ <http://www.erlang.org/download.html>) and unpack with
+ Cygwin's/MSYS's/MSYS2's `tar`.
+
+ * Set `ERL_TOP` to where you unpacked the source distribution
+
+ * `$ cd $ERL_TOP`
+
+ * Modify PATH and other environment variables so that all these tools
+ are runnable from a bash shell. Still standing in `$ERL_TOP`, issue
+ the following commands (for 32-bit Windows, remove the x64 from the
+ first row and change `otp_win64_%OTP-REL%` to `otp_win32_%OTP-REL%` on
+ the last row):
+
+ $ eval `./otp_build env_win32 x64`
+ $ ./otp_build autoconf
+ $ ./otp_build configure
+ $ ./otp_build boot -a
+ $ ./otp_build release -a
+ $ ./otp_build installer_win32
+ $ release/win32/otp_win64_%OTP-REL% /S
+
+ Voila! `Start->Programs->Erlang OTP %OTP-REL%->Erlang` starts the Erlang
+ Windows shell.
Frequently Asked Questions
@@ -88,12 +116,12 @@ Frequently Asked Questions
* Q: So, now I can build Erlang using GCC on Windows?
A: No, unfortunately not. You'll need Microsoft's Visual C++
- still, a Bourne-shell script (cc.sh) wraps the Visual C++ compiler
+ still. A Bourne-shell script (cc.sh) wraps the Visual C++ compiler
and runs it from within the Cygwin environment. All other tools
needed to build Erlang are free-ware/open source, but not the C
compiler. The Windows SDK is however enough to build Erlang, you
do not need to buy Visual C++, just download the SDK (SDK version
- 7.1 == Visual studio 2010).
+ 8.1 == Visual studio 2013).
* Q: Why haven't you got rid of VC++ then, you \*\*\*\*\*\*?
@@ -106,18 +134,17 @@ Frequently Asked Questions
mingw build will possibly be back, but as long as VC++ gives better
performance, the commercial build will be a VC++ one.
-* Q: OK, you need VC++, but now you've started to demand a very recent
- (and expensive) version of Visual studio, not the old and stable VC++
- 6.0 that was used in earlier versions. Why?
+* Q: OK, you need VC++, but now you've started to demand a quite recent
+ (and expensive) version of Visual Studio. Why?
A: Well, it's not expensive, it's free (as in free beer). Just
download and install the latest Windows SDK from Microsoft and all
the tools you need are there. The included debugger (WinDbg) is
- also quite usable, it's what I used when porting Erlang to 64bit
- Windows. Another reason to use the latest Microsoft compilers is
+ also quite usable. That's what I used when porting Erlang to 64bit
+ Windows. Another reason to use later Microsoft compilers is
DLL compatibility. DLL's using a new version of the standard
library might not load if the VM is compiled with an old VC++
- version, why we should aim to use the latest freely available SDK
+ version. So we should aim to use the latest freely available SDK
and compiler.
* Q: Can/will I build a Cygwin binary with the procedure you describe?
@@ -130,9 +157,7 @@ Frequently Asked Questions
some problems. Fixing those problems might be easy or might be hard.
I suggest you try yourself and share your experience. No one would be
happier if a simple `./configure && make` would produce a fully fledged
- Cygwin binary. Ericsson does however not pay me to do a Cygwin port, so
- such a port would have to happen in spare time, which is a limited
- resource...
+ Cygwin binary.
* Q: Hah, I saw you, you used GCC even though you said you didn't!
@@ -142,7 +167,7 @@ Frequently Asked Questions
particular file, `beam_emu.c` benefits immensely from being able
to use the GCC labels-as-values extension, which boosts emulator
performance by up to 50%. That does unfortunately not (yet) mean
- that all of OTP could be compiled using GCC, that particular
+ that all of OTP could be compiled using GCC. That particular
source code does not do anything system specific and actually is
adopted to the fact that GCC is used to compile it on Windows.
@@ -152,229 +177,184 @@ Frequently Asked Questions
A: No, never. The hassle of keeping the project files up to date and
do all the steps that constitute an OTP build from within the VC++ GUI
is simply not worth it, maybe even impossible. A VC++ project
- file for Erlang/OTP will never happen, at least I will never make
- one. Clicking around in super-multi-tab'd dialogs to add a file or
- compiler option when it's so much easier in a makefile is simply not
- my style.
+ file for Erlang/OTP will never happen.
* Q: So how does it all work then?
- A: Cygwin or Msys is the environment, which closely resembles the
- environments found on any Unix machine. It's almost like you had a
+ A: Cygwin, MSYS or MSYS2 is the environment, which closely resembles the
+ environment found on any Unix machine. It's almost like you had a
virtual Unix machine inside Windows. Configure, given certain
parameters, then creates makefiles that are used by the
- Cygwin/Msys gnu-make to built the system. Most of the actual
- compilers etc are not, however, Cygwin/Msys tools, so I've written
+ environment's gnu-make to built the system. Most of the actual
+ compilers etc are not, however, Cygwin/MSYS/MSYS2 tools, so we've written
a couple of wrappers (Bourne-shell scripts), which reside in
`$ERL_TOP/etc/win32/cygwin_tools` and
`$ERL_TOP/etc/win32/msys_tools`. They all do conversion of
parameters and switches common in the Unix environment to fit the
native Windows tools. Most notable is of course the paths, which
- in Cygwin/Msys are Unix-like paths with "forward slashes" (/) and
- no drive letters, the Cygwin specific command `cygpath` is used
- for most of the path conversions in a Cygwin environment, other
- tools are used (when needed) in the corresponding Msys
+ in Cygwin/MSYS/MSYS2 are Unix-like paths with "forward slashes" (/) and
+ no drive letters. The Cygwin specific command `cygpath` is used
+ for most of the path conversions in a Cygwin environment. Other
+ tools are used (when needed) in the corresponding MSYS and MSYS2
environment. Luckily most compilers accept forward slashes instead
of backslashes as path separators, but one still have to get the drive
letters etc right, though. The wrapper scripts are not general in
- the sense that, for example, cc.sh would understand and translates
- every possible gcc option and passes correct options to
+ the sense that, for example, cc.sh would understand and translate
+ every possible gcc option and pass correct options to
cl.exe. The principle is that the scripts are powerful enough to
allow building of Erlang/OTP, no more, no less. They might need
- extensions to cope with changes during the development of Erlang,
- that's one of the reasons I made them into shell-scripts and not
- Perl-scripts, I believe they are easier to understand and change
- that way. I might be wrong though, cause another reason I didn't
- write them in Perl is because I've never liked Perl and my Perl
- code is no pleasant reading...
+ extensions to cope with changes during the development of Erlang, and
+ that's one of the reasons we made them into shell-scripts and not
+ Perl-scripts. We believe they are easier to understand and change
+ that way.
In `$ERL_TOP`, there is a script called `otp_build`. That script handles
the hassle of giving all the right parameters to `configure`/`make` and
also helps you set up the correct environment variables to work with
- the Erlang source under Cygwin.
+ the Erlang source under Cygwin/MSYS/MSYS2.
* Q: You use and need Cygwin, but then you haven't taken the time to
port Erlang to the Cygwin environment but instead focus on your
commercial release, is that really ethical?
- A: No, not really, but see this as a step in the right direction. I'm
- aiming at GCC compiled emulators and a Cygwin version, but I really
- need to do other things as well... In time, but don't hold your
- breath...
+ A: No, not really, but see this as a step in the right direction.
* Q: Can I build something that looks exactly as the commercial release?
- A: Yes, we use the exactly same build procedure.
+ A: Yes, we use the exact same build procedure.
-* Q: Which version of Cygwin/Msys and other tools do you use then?
+* Q: Which version of Cygwin/MSYS/MSYS2 and other tools do you use then?
- A: For Cygwin and Msys alike, we try to use the latest releases
+ A: For Cygwin, MSYS and MSYS2 alike, we try to use the latest releases
available when building. What versions you use shouldn't really
- matter, I try to include workarounds for the bugs I've found in
- different Cygwin/Msys releases, please help me add workarounds
- for new Cygwin/Msys-related bugs as soon as you encounter
- them. Also please do submit bug reports to the appropriate Cygwin
- and/or Msys developers. The GCC we used for %OTP-REL% was version
- 4.7.0 (MinGW 64bit) and 4.3.4 (Cygwin 32bit). We used VC++ 10.0
- (i.e. Visual studio 2010), Sun's JDK 1.5.0\_17 (32bit) and Sun's
- JDK 1.7.0\_1 (64bit), NSIS 2.46, and Win32 OpenSSL 0.9.8r. Please
+ matter. We try to include workarounds for the bugs we've found in
+ different Cygwin/MSYS/MSYS2 releases. Please help us add workarounds
+ for new Cygwin/MSYS/MSYS2-related bugs as soon as you encounter
+ them. Also please do submit bug reports to the appropriate Cygwin, MSYS
+ and/or MSYS2 developers. The GCC we used for %OTP-REL% was version
+ 4.8.1 (MinGW 32bit) and 4.8.5 (MSYS2 64bit). We used VC++ 12.0
+ (i.e. Visual studio 2013), Sun's JDK 1.6.0\_45 (32bit) and Sun's
+ JDK 1.7.0\_1 (64bit), NSIS 2.46, and Win32 OpenSSL 1.0.2d. Please
read the next section for details on what you need.
-* Q: Can you help me setup X in Cygwin?
+* Q: Can you help me setup X in Cygwin/MSYS/MSYS2?
- A: No, unfortunately I haven't got time to help with Cygwin related
- user problems, please read Cygwin related web sites, newsgroups and
+ A: No, unfortunately we haven't got time to help with Cygwin/MSYS/MSYS2
+ related user problems, please read related websites, newsgroups and
mailing lists.
-* Q: Why is the instruction so long? Is it really that complicated?
-
- A: Partly it's long because I babble too much, partly because I've
- described as much as I could about the installation of the needed
- tools. Once the tools are installed, building is quite easy. I also
- have tried to make this instruction understandable for people with
- limited Unix experience. Cygwin/Msys is a whole new environment to some
- Windows users, why careful explanation of environment variables etc
- seemed to be in place. The short story, for the experienced and
- impatient is:
-
- * Get and install complete Cygwin (latest) or complete MinGW with msys
-
- * Install Microsofts Windows SDK 7.1 (and .Net 4)
-
- * Get and install Sun's JDK 1.5.0 or higher
-
- * Get and install NSIS 2.01 or higher (up to 2.46 tried and working)
-
- * Get, build and install OpenSSL 0.9.8r or higher (up to 1.0.0a
- tried & working) with static libs.
-
- * Get the Erlang source distribution (from
- <http://www.erlang.org/download.html>) and unpack with Cygwin's `tar`.
-
- * Set `ERL_TOP` to where you unpacked the source distribution
-
- * `$ cd $ERL_TOP`
-
- * Get (from <http://www.erlang.org/download/tcltk85_win32_bin.tar.gz>)
- and unpack the prebuilt TCL/TK binaries for windows with cygwin tar,
- standing in `$ERL_TOP`
-
- * Modify PATH and other environment variables so that all these tools
- are runnable from a bash shell. Still standing in `$ERL_TOP`, issue
- the following commands:
-
- $ eval `./otp_build env_win32`
- $ ./otp_build autoconf
- $ ./otp_build configure
- $ ./otp_build boot -a
- $ ./otp_build release -a
- $ ./otp_build installer_win32
- $ release/win32/otp_win32_%OTP-REL% /S
-
- Voila! `Start->Programs->Erlang OTP %OTP-REL%->Erlang` starts the Erlang
- Windows shell.
-
Tools you Need and Their Environment
------------------------------------
You need some tools to be able to build Erlang/OTP on Windows. Most
-notably you'll need Cygwin or Msys and Microsofts Windows SDK, but
-you also might want a Java compiler, the NSIS install system and
-OpenSSL. Well' here's the list:
+notably you'll need Cygwin, MSYS or MSYS2, Visual Studio and Microsofts
+Windows SDK, but you might also want a Java compiler, the NSIS install
+system and OpenSSL. Well, here's some information about the different
+tools:
* Cygwin, the very latest is usually best. Get all the development
- tools and of course all the basic ditto. In fact getting the complete
- package might be a good idea, as you'll start to love Cygwin after a
- while if you're accustomed to Unix. Make sure to get jar and also make
- sure *not* to install a Cygwin'ish Java... The Cygwin jar command is
- used but Sun's Java compiler and virtual machine...
+ tools and of course all the basic ditto. Make sure to get jar and
+ also make sure *not* to install a Cygwin'ish Java, since the Cygwin
+ jar command is used but Sun's Java compiler and virtual machine.
If you are going to build a 64bit Windows version, you should make
- sure to get MinGW's 64bit gcc installed with cygwin. It's in one of
+ sure to get MinGW's 64bit gcc installed with Cygwin. It's in one of
the development packages.
URL: <http://www.cygwin.com>
- Get the installer from the web site and use that to install
- Cygwin. Be sure to have fair privileges. If you're on a NT domain you
+ Get the installer from the website and use it to install
+ Cygwin. Be sure to have fair privileges. If you're on an NT domain you
should consider running `mkpasswd -d` and `mkgroup -d` after the
installation to get the user databases correct. See their respective
manual pages.
- When you start you first bash shell, you will get an awful prompt. You
+ When you start your first bash shell, you will get an awful prompt. You
might also have a `PATH` environment variable that contains backslashes
and such. Edit `$HOME/.profile` and `$HOME/.bashrc` to set fair prompts
- and set a correct PATH. Also do a `export SHELL` in `.profile`. For some
+ and a correct PATH. Also do an `export SHELL` in `.profile`. For some
non-obvious reason the environment variable `$SHELL` is not exported in
bash. Also note that `.profile` is run at login time and `.bashrc` when
sub shells are created. You'll need to explicitly source `.bashrc` from
`.profile` if you want the commands there to be run at login time (like
- setting up aliases, shell functions and the like). I personally
- usually do like this at the end of `.profile`:
+ setting up aliases, shell functions and the like). You can for example
+ do like this at the end of `.profile`:
ENV=$HOME/.bashrc
export ENV
. $ENV
- You might also, if you're a hard core type of person at least, want to
- setup X-windows (XFree86), that might be as easy as running startx
- from the command prompt and it might be much harder. Use Google to
- find help...
+ You might also want to setup X-windows (XFree86). That might be as easy
+ as running startx from the command prompt and it might be much harder.
+ Use Google to find help.
If you don't use X-windows, you might want to setup the Windows
console window by selecting properties in the console system menu
(upper left corner of the window, the Cygwin icon in the title
bar). Especially setting a larger screen buffer size (lines) is useful
as it gets you a scrollbar so you can see whatever error messages
- that might appear...
+ that might appear.
- If you want to use (t)csh instead of bash you're on your own, I
- haven't tried and know of no one that has. I expect
- that you use bash in all shell examples.
+ There are a few other shells available, but in all examples below we assume
+ that you use bash.
-* Alternatively you download MinGW and Msys. You'll find the latest
+* Alternatively you download MinGW and MSYS. You'll find the latest
installer at:
URL: <http://sourceforge.net/projects/mingw/files/Installer/mingw-get-inst/>
- Make sure to install everything they've got.
+ Make sure to install the basic dev tools, but avoid the MinGW autoconf and
+ install the msys one instead.
To be able to build the 64bit VM, you will also need the 64bit
MinGW compiler from:
- URL: <http://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win64/Automated%20Builds/>
+ URL: <http://sourceforge.net/projects/mingw-w64/files/latest/download?source=files>
- The latest version should do it. Make sure you download the
- `mingw-w64-bin_i686-mingw_<something>.zip`, not a linux
+ We've tried up to 1.0, but the latest version should do. Make sure you
+ download the `mingw-w64-bin_i686-mingw_<something>.zip`, not a linux
version. You unzip the package on top of your MinGW installation
(`c:\MinGW`) and that's it.
- Setting up your environment in Msys is similar to setting it up in
- Cygwin.
+* A third alternative is to download and install MSYS2 from:
-* Microsofts Windows SDK version 7.1 (corresponding to VC++ 10.0 and
- Visual Studio 2010). You'll find it here:
-
- URL: <http://www.microsoft.com/download/en/details.aspx?id=8279>
+ URL: <https://msys2.github.io/>
+
+ When you've followed the instructions there, you also need to install
+ these packages: autoconf, make, perl, and tar. You do so by running
+ the following in the msys console:
+
+ pacman -S msys/autoconf msys/make msys/perl msys/tar
+
+ You also need a gcc. If you installed the 64 bit MSYS2 you run:
- but before you install that, you need to have .Net 4 installed,
- you'll find that here:
+ mingw64/mingw-w64-x86_64-gcc
- URL: <http://www.microsoft.com/download/en/details.aspx?id=17851>
+ And for 32 bit MSYS2:
- Use the web installer for the SDK, at least when I tried
- downloading the whole package as an image, I got SDK 7.0 instead,
- which is not what you want...
+ pacman -S mingw32/mingw-w64-i686-gcc
+ pacman -S mingw-w64-i686-editrights
- There will be a Windows command file in `%PROGRAMFILES%\Mirosoft
- SDKs\Windows\v7.1\Bin\SetEnv.cmd` that set's the appropriate
+* Visual Studio 2013 (Visual Studio 12.0). Download and run the web
+ installer from:
+
+ https://www.visualstudio.com/
+
+* Microsofts Windows SDK version 8.1 (corresponding to VC++ 12.0 and
+ Visual Studio 2013). You'll find it here:
+
+ URL: <https://msdn.microsoft.com/en-us/windows/desktop/bg162891.aspx>
+
+* To help setup the environment, there is a bat file,
+ `%PROGRAMFILES%\Mirosoft Visual Studio 12.0\VC\vcvarsall.bat`,
+ that set's the appropriate
environment for a Windows command prompt. This is not appropriate
for bash, so you'll need to convert it to bash-style environments
by editing your `.bash_profile`. In my case, where the SDK is
installed in the default directory and `%PROGRAMFILES%` is
`C:\Program Files`, the commands for setting up a 32bit build
- environment (on a 64bit or 32bit machine) look like this (in cygwin):
+ environment (on a 64bit or 32bit machine) look like this (in Cygwin):
# Some common paths
C_DRV=/cygdrive/c
@@ -383,309 +363,290 @@ OpenSSL. Well' here's the list:
# nsis
NSIS_BIN=$PRG_FLS/NSIS
# java
- JAVA_BIN=$PRG_FLS/Java/jdk1.6.0_16/bin
+ JAVA_BIN=$PROGRAMFILES/Java/jdk1.7.0_02/bin
##
## MS SDK
##
- CYGWIN=nowinsymlinks
- MVS10="$PRG_FILES/Microsoft Visual Studio 10.0"
- WIN_MVS10="C:\\Program Files\\Microsoft Visual Studio 10.0"
- SDK10="$PRG_FILES/Microsoft SDKs/Windows/v7.1"
- WIN_SDK10="C:\\Program Files\\Microsoft SDKs\\Windows\\v7.1"
+ CYGWIN=nowinsymlinks
+
+ VISUAL_STUDIO_ROOT=$PRG_FLS/Microsoft\ Visual\ Studio\ 12.0
+ WIN_VISUAL_STUDIO_ROOT="C:\\Program Files\\Microsoft Visual Studio 12.0"
+ SDK=$PRG_FLS/Windows\ Kits/8.1
+ WIN_SDK="C:\\Program Files\\Windows Kits\\8.1"
PATH="$NSIS_BIN:\
- $MVS10/Common7/IDE:\
- $MVS10/Common7/Tools:\
- $MVS10/VC/Bin:\
- $MVS10/VC/Bin/VCPackages:\
- $SDK10/Bin/NETFX 4.0 Tools:\
- $SDK10/Bin:\
+ $VISUAL_STUDIO_ROOT/VC/bin:\
+ $VISUAL_STUDIO_ROOT/VC/vcpackages:\
+ $VISUAL_STUDIO_ROOT/Common7/IDE:\
+ $VISUAL_STUDIO_ROOT/Common7/Tools:\
+ $SDK/bin/x86
/usr/local/bin:/usr/bin:/bin:\
/cygdrive/c/WINDOWS/system32:/cygdrive/c/WINDOWS:\
/cygdrive/c/WINDOWS/system32/Wbem:\
$JAVA_BIN"
- LIBPATH="$WIN_MVS10\\VC\\LIB"
+ LIBPATH="$WIN_VISUAL_STUDIO_ROOT\\VC\\lib"
- LIB="$WIN_MVS10\\VC\\LIB;$WIN_SDK10\\LIB"
+ LIB="$WIN_VISUAL_STUDIO_ROOT\\VC\\lib\\;$WIN_SDK\\lib\\winv6.3\\um\\x86"
- INCLUDE="$WIN_MVS10\\VC\\INCLUDE;$WIN_SDK10\\INCLUDE;$WIN_SDK10\\INCLUDE\\gl"
+ INCLUDE="$WIN_VISUAL_STUDIO_ROOT\\VC\\include\\;$WIN_SDK\\include\\shared\\;
+ $WIN_SDK\\include\\um;$WIN_SDK\\include\\winrt\\;$WIN_SDK\\include\\um\\gl"
- export CYGWIN PATH LIBPATH LIB INCLUDE
+ export CYGWIN PATH LIBPATH LIB INCLUDE
- If you're using Msys instead, the only thing you need to change is
- the `C_DRV` setting, which would read:
+ If you're using MinGW's MSYS instead, you need to change the `C_DRV` setting,
+ which would read:
C_DRV=/c
- And of course you might need to change `C:\Program Files` etc if
- you're using a non-english version of Windows (XP). Note that in
- later versions of Windows, the national adoptions of the program
- files directories etc are not on the file system but only in the
- explorer, so even if explorer says that your programs reside in
- e.g. `C:\Program`, they might still reside in `C:\Program Files`
- in reality...
-
- If you are building a 64 bit version of Erlang, you should set up
- PATHs etc a little differently. I use the following script to
- make things work in both Cygwin and Msys:
-
- make_winpath()
- {
- P=$1
- if [ "$IN_CYGWIN" = "true" ]; then
- cygpath -d "$P"
- else
- (cd "$P" && /bin/cmd //C "for %i in (".") do @echo %~fsi")
- fi
- }
-
- make_upath()
- {
- P=$1
- if [ "$IN_CYGWIN" = "true" ]; then
- cygpath "$P"
- else
- echo "$P" | /bin/sed 's,^\([a-zA-Z]\):\\,/\L\1/,;s,\\,/,g'
- fi
- }
-
- # Some common paths
- if [ -x /usr/bin/msysinfo ]; then
- # Without this the path conversion won't work
- COMSPEC='C:\Windows\SysWOW64\cmd.exe'
- MSYSTEM=MINGW32
- export MSYSTEM COMSPEC
- IN_CYGWIN=false
- else
- CYGWIN=nowinsymlinks
- export CYGWIN
- IN_CYGWIN=true
- fi
-
- if [ "$IN_CYGWIN" = "true" ]; then
- PATH=/usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin:\
- /cygdrive/c/windows/system32:/cygdrive/c/windows:/cygdrive/c/windows/system32/Wbem
- else
- PATH=/usr/local/bin:/mingw/bin:/bin:/c/Windows/system32:/c/Windows:\
- /c/Windows/System32/Wbem
- fi
-
- if [ "$IN_CYGWIN" = "true" ]; then
- C_DRV=/cygdrive/c
- else
- C_DRV=/c
- fi
-
- PRG_FLS64=$C_DRV/Program\ Files
- PRG_FLS32=$C_DRV/Program\ Files\ \(x86\)
- VISUAL_STUDIO_ROOT32=$PRG_FLS32/Microsoft\ Visual\ Studio\ 10.0
- MS_SDK_ROOT64=$PRG_FLS64/Microsoft\ SDKs/Windows/v7.1
-
- # Okay, now mangle the paths and get rid of spaces by using short names
- WIN_VCROOT32=`make_winpath "$VISUAL_STUDIO_ROOT32"`
- VCROOT32=`make_upath $WIN_VCROOT32`
- WIN_SDKROOT64=`make_winpath "$MS_SDK_ROOT64"`
- SDKROOT64=`make_upath $WIN_SDKROOT64`
- WIN_PROGRAMFILES32=`make_winpath "$PRG_FLS32"`
- PROGRAMFILES32=`make_upath $WIN_PROGRAMFILES32`
-
- WIN_PROGRAMFILES64=`make_winpath "$PRG_FLS64"`
- PROGRAMFILES64=`make_upath $WIN_PROGRAMFILES64`
-
- # nsis
- NSIS_BIN=$PROGRAMFILES32/NSIS
- # java
- JAVA_BIN=$PROGRAMFILES64/Java/jdk1.7.0_01/bin
-
- ## The PATH variable should be Unix'ish
- VCPATH=$VCROOT32/Common7/IDE:$VCROOT32/VC/BIN/amd64:$VCROOT32/Common7/Tools:\
- $VCROOT32/VC/VCPackages:$SDKROOT64/bin/NETFX4~1.0TO/x64:$SDKROOT64/bin/x64:\
- $SDKROOT64/bin
-
- ## Microsoft SDK libs
-
- LIBPATH=$WIN_VCROOT32\\VC\\LIB\\amd64
- LIB=$WIN_VCROOT32\\VC\\LIB\\amd64\;$WIN_SDKROOT64\\LIB\\X64
- INCLUDE=$WIN_VCROOT32\\VC\\INCLUDE\;$WIN_SDKROOT64\\include\;\
- $WIN_SDKROOT64\\include\\gl
-
- # Put nsis, c compiler and java in path
- PATH=$NSIS_BIN:$VCPATH:$PATH:$JAVA_BIN
-
- # Make sure LIB and INCLUDE is available for others
- export PATH LIBPATH LIB INCLUDE
-
- All this is derived from the SetEnv.cmd command file mentioned
- earlier. The bottom line is to set the PATH so that NSIS and
- Microsoft SDK is found before the Msys/Cygwin tools and that Java
- is last in the PATH.
-
- Make a simple hello world (maybe one that prints out
- `sizeof(void *)`) and try to compile it with the `cl` command from within
- bash. If that does not work, your environment needs fixing. Also
- remember to fix up the PATH environment, especially old Erlang
- installations might have inserted quoted paths that Cygwin/Msys
- does not understand. Remove or correct such paths. There should be
- no backslashes in your path environment variable in Cygwin bash,
- but LIB and INCLUDE should contain Windows style paths with
- semicolon, drive letters and backslashes.
+ and you also need to change the PATH environment variable to:
-* Sun's Java JDK 1.5.0 or higher. Our Java code (jinterface, ic) is
- written for JDK 1.5.0. Get it for Windows and install it, the JRE is
- not enough. If you don't care about Java, you can skip this step, the
- result will be that jinterface is not built.
+ MINGW_BIN=/c/MinGW/bin
- URL: <http://java.sun.com>
- Add javac *LAST* to your path environment in bash, in my case this means:
+ PATH="$NSIS_BIN:\
+ $VISUAL_STUDIO_ROOT/VC/bin:\
+ $VISUAL_STUDIO_ROOT/VC/vcpackages:\
+ $VISUAL_STUDIO_ROOT/Common7/IDE:\
+ $VISUAL_STUDIO_ROOT/Common7/Tools:\
+ $SDK/bin/x86:/usr/local/bin:\
+ $MINGW_BIN:\
+ /bin:/c/Windows/system32:/c/Windows:\
+ /c/Windows/System32/Wbem:\
+ $JAVA_BIN"
- `PATH="$PATH:/cygdrive/c/Program Files/Java/jdk1.5.0_17/bin"`
+ For MSYS2 you use the same `C_DRV` and PATH as for MSYS, only update the `MINGW_BIN`:
- No `CLASSPATH` or anything is needed. Type `javac` at the bash prompt
- and you should get a list of available Java options. Make sure by
- typing `type java` that you use the Java you installed. Note however that
- Cygwin's `jar.exe` is used, that's why the JDK bin-directory should be
- added last in the `PATH`.
+ MINGW_BIN=/mingw32/bin
+
-* Nullsoft NSIS installer system. You need this to build the self
- installing package. It's a free open source installer that's much
- nicer to use than the commercial Wise and Install shield
- installers. This is the installer we use for commercial releases as
- well from R9C an on.
+ If you are building a 64 bit version of Erlang, you should set up
+ PATHs etc a little differently. We have two templates to make things
+ work in both Cygwin and MSYS but needs editing to work with MSYS2 (see the
+ comments in the script).
+ The following one is for 32 bits:
+
+ make_winpath()
+ {
+ P=$1
+ if [ "$IN_CYGWIN" = "true" ]; then
+ cygpath -d "$P"
+ else
+ (cd "$P" && /bin/cmd //C "for %i in (".") do @echo %~fsi")
+ fi
+ }
+
+ make_upath()
+ {
+ P=$1
+ if [ "$IN_CYGWIN" = "true" ]; then
+ cygpath "$P"
+ else
+ echo "$P" | /bin/sed 's,^\([a-zA-Z]\):\\,/\L\1/,;s,\\,/,g'
+ fi
+ }
- URL: <http://www.nullsoft.com/free/nsis>
+ # Some common paths
+ if [ -x /usr/bin/msys-?.0.dll ]; then
+ # Without this the path conversion won't work
+ COMSPEC='C:\Windows\System32\cmd.exe'
+ MSYSTEM=MINGW32 # Comment out this line if in MSYS2
+ export MSYSTEM COMSPEC
+ # For MSYS2: Change /mingw/bin to the msys bin dir on the line below
+ PATH=/usr/local/bin:/mingw/bin:/bin:/c/Windows/system32:\
+ /c/Windows:/c/Windows/System32/Wbem
+ C_DRV=/c
+ IN_CYGWIN=false
+ else
+ PATH=/ldisk/overrides:/usr/local/bin:/usr/bin:/bin:\
+ /usr/X11R6/bin:/cygdrive/c/windows/system32:\
+ /cygdrive/c/windows:/cygdrive/c/windows/system32/Wbem
+ C_DRV=/cygdrive/c
+ IN_CYGWIN=true
+ fi
+
+ obe_otp_gcc_vsn_map="
+ .*=>default
+ "
+ obe_otp_64_gcc_vsn_map="
+ .*=>default
+ "
+ # Program Files
+ PRG_FLS=$C_DRV/Program\ Files
- Install the lot, especially the modern user interface components, as
- it's definitely needed. Put `makensis` in your path, in my case:
+ # Visual Studio
+ VISUAL_STUDIO_ROOT=$PRG_FLS/Microsoft\ Visual\ Studio\ 12.0
+ WIN_VISUAL_STUDIO_ROOT="C:\\Program Files\\Microsoft Visual Studio 12.0"
- PATH=/cygdrive/c/Program\ Files/NSIS:$PATH
+ # SDK
+ SDK=$PRG_FLS/Windows\ Kits/8.1
+ WIN_SDK="C:\\Program Files\\Windows Kits\\8.1"
- type makensis at the bash prompt and you should get a list of options
- if everything is OK.
+ # NSIS
+ NSIS_BIN=$PROGRAMFILES/NSIS
-* OpenSSL. This is if you want the SSL and crypto applications to
- compile (and run). There are prebuilt binaries available, but I
- strongly recommend building this yourself. It's quite easy.
+ # Java
+ JAVA_BIN=$PROGRAMFILES/Java/jdk1.7.0_02/bin
- First get the source from
+ ## The PATH variable should be Cygwin'ish
+ VCPATH=
+ $VISUAL_STUDIO_ROOT/VC/bin:\
+ $VISUAL_STUDIO_ROOT/VC/vcpackages:\
+ $VISUAL_STUDIO_ROOT/Common7/IDE:\
+ $VISUAL_STUDIO_ROOT/Common7/Tools:\
+ $SDK/bin/x86
- URL: <http://openssl.org/source/>
+ ## Microsoft SDK libs
+ LIBPATH=$WIN_VISUAL_STUDIO_ROOT\\VC\\lib
- I would recommend using 0.9.8r.
+ LIB=$WIN_VISUAL_STUDIO_ROOT\\VC\\lib\\;$WIN_KITS\\lib\\winv6.3\\um\\x86
- Download the tar file and unpack it (using your bash prompt) into
- a directory of your choise.
+ INCLUDE=$WIN_VISUAL_STUDIO_ROOT\\VC\\include\\;\
+ $WIN_KITS\\include\\shared\\;$WIN_KITS\\include\\um;\
+ $WIN_KITS\\include\\winrt\\;$WIN_KITS\\include\\um\\gl
- You will need a Windowish Perl for the build. ActiveState has one:
+ # Put nsis, c compiler and java in path
+ export PATH=$VCPATH:$PATH:$JAVA_BIN:$NSIS_BIN
- URL: <http://www.activestate.com/activeperl/downloads>
+ # Make sure LIB and INCLUDE is available for others
+ export LIBPATH LIB INCLUDE
- Download and install that. Disable options to associate it with
- the .pl suffix and/or adding things to PATH, they are not needed.
- Now fire up the Microsoft Windows SDK command prompt in RELEASE
- mode for the architecture you are going to build. The easiest is
- to copy the shortcut from the SDKs start menu item and edit the
- command line in the shortcut (Right click->Properties) to end with
- `/Release`. Make sure the banner when you double click your
- shortcut (the text in the resulting command window) says
- `Targeting Windows XP x64 Release` if you are going to do a 64 bit
- build and `Targeting Windows XP x86 Release` if you are building a
- 32 bit version.
- Now cd to where you unpacked the OpenSSL source using your Release
- Windows command prompt (it should be on the same drive as where
- you are going to install it if everything is to work smothly).
+ The first part of the 64 bit template is identical to the 32 bit one,
+ but there are some environment variable differences:
- C:\> cd <some dir>
+ # Program Files
+ PRG_FLS64=$C_DRV/Program\ Files
+ PRG_FLS32=$C_DRV/Program\ Files\ \(x86\)
- Add ActiveState (or some other windows perl, not cygwins) to your PATH:
+ # Visual Studio
+ VISUAL_STUDIO_ROOT=$PRG_FLS32/Microsoft\ Visual\ Studio\ 12.0
+ WIN_VISUAL_STUDIO_ROOT="C:\\Program Files (x86)\\Microsoft Visual Studio 12.0"
- C:\...\> set PATH=C:\Perl\bin;%PATH%
+ # SDK
+ SDK=$PRG_FLS32/Windows\ Kits/8.1
+ WIN_SDK="C:\\Program Files (x86)\\Windows Kits\\8.1"
- Or if you installed the 64bit perl:
-
- C:\...\> set PATH=C:\Perl64\bin;%PATH%
+ # NSIS
+ NSIS_BIN=$PROGRAMFILES/NSIS
+ # Java
+ JAVA_BIN=$PROGRAMFILES/Java/jdk1.7.0_02/bin
- Configure OpenSSL for 32 bit:
+ ## The PATH variable should be Cygwin'ish
+ VCPATH=
+ $VISUAL_STUDIO_ROOT/VC/bin/amd64:\
+ $VISUAL_STUDIO_ROOT/VC/vcpackages:\
+ $VISUAL_STUDIO_ROOT/Common7/IDE:\
+ $VISUAL_STUDIO_ROOT/Common7/Tools:\
+ $SDK/bin/x86
- C:\...\> perl Configure VC-WIN32 --prefix=/OpenSSL
+ ## Microsoft SDK libs
+ LIBPATH=$WIN_VISUAL_STUDIO_ROOT\\VC\\lib\\amd64
- Or for 64 bit:
+ LIB=$WIN_VISUAL_STUDIO_ROOT\\VC\\lib\\amd64\\;\
+ $WIN_KITS\\lib\\winv6.3\\um\\x64
- C:\...\> perl Configure VC-WIN64A --prefix=/OpenSSL-Win64
+ INCLUDE=$WIN_VISUAL_STUDIO_ROOT\\VC\\include\\;\
+ $WIN_KITS\\include\\shared\\;$WIN_KITS\\include\\um;\
+ $WIN_KITS\\include\\winrt\\;$WIN_KITS\\include\\um\\gl
- Do some setup (for 32 bit):
+ # Put nsis, c compiler and java in path
+ export PATH=$VCPATH:$PATH:$JAVA_BIN:$NSIS_BIN
- C:\...\> ms\do_ms
+ # Make sure LIB and INCLUDE is available for others
+ export LIBPATH LIB INCLUDE
- The same for 64 bit:
- C:\...\> ms\do_win64a
+ Make sure to set the PATH so that NSIS and Microsoft SDK is found
+ before the MSYS/Cygwin tools and that Java is last in the PATH.
- Then build static libraries and install:
+ Make a simple hello world and try to compile it with the `cl`
+ command from within bash. If that does not work, your environment
+ needs fixing. Remember, there should be
+ no backslashes in your path environment variable in Cygwin bash,
+ but LIB and INCLUDE should contain Windows style paths with
+ semicolon, drive letters and backslashes.
- C:\...\> nmake -f ms\nt.mak
- C:\...\> nmake -f ms\nt.mak install
+* Sun's Java JDK 1.6.0 or later. Our Java code (jinterface, ic) is
+ written for JDK 1.6.0. Get it for Windows and install it, the JRE is
+ not enough. If you don't care about Java, you can skip this step. The
+ result will be that jinterface is not built.
+
+ URL: <http://java.sun.com>
+
+ Add javac *LAST* to your path environment in bash, in my case this means:
+
+ `PATH="$PATH:/cygdrive/c/Program Files/Java/jdk1.7.0_02/bin"`
+
+ No `CLASSPATH` or anything is needed. Type `javac` in the bash prompt
+ and you should get a list of available Java options. Make sure, e.g by
+ typing `type java`, that you use the Java you installed. Note however that
+ Cygwin's/MinGW's/MSYS2's `jar.exe` is used. That's why the JDK bin-directory should be
+ added last in the `PATH`.
+
+* Nullsoft NSIS installer system. You need this to build the self
+ installing package. It's a free open source installer that's much
+ nicer to use than the commercial Wise and Install shield
+ installers. This is the installer we use for commercial releases as
+ well.
+
+ URL: <http://nsis.sourceforge.net/download>
+
+ Install the lot, especially the modern user interface components, as
+ it's definitely needed. Put `makensis` in your path, in my case:
+
+ PATH=/cygdrive/c/Program\ Files/NSIS:$PATH
+
+ Type makensis at the bash prompt and you should get a list of options
+ if everything is OK.
+
+* OpenSSL. This is if you want the SSL and crypto applications to
+ compile (and run). There are prebuilt binaries, which you can just
+ download and install, available here:
+
+ URL: <http://openssl.org/community/binaries.html>
- That's it - you now have your perfectly consistent static build of
- openssl. If you want to get rid of any possibly patented
- algorithms in the lib, just read up on the OpenSSL FAQ and follow
- the instructions.
+ We would recommend using 1.0.2d.
- The installation locations chosen are where configure will look
- for OpenSSL, so try to keep them as is.
-
-* Building with wxWidgets. Download wxWidgets-3.0.2 or higher patch
- release.
+* Building with wxWidgets. Download wxWidgets-3.0.2 or higher.
- Install or unpack it to `DRIVE:/PATH/cygwin/opt/local/pgm`.
+ Install or unpack it to the pgm folder:
+ Cygwin:
+ `DRIVE:/PATH/cygwin/opt/local/pgm`
+ MSYS:
+ `DRIVE:/PATH/MinGW/msys/1.0/opt/local/pgm`
+ MSYS2:
+ `DRIVE:/PATH/msys<32/64>/opt/local/pgm`
- edit: `C:\cygwin\opt\local\pgm\wxMSW-3.0.2\include\wx\msw\setup.h`
- enable `wxUSE_POSTSCRIPT`
+ If the `wxUSE_POSTSCRIPT` isn't enabled in `<path\to\pgm>\wxMSW-3.0.2\include\wx\msw\setup.h`,
+ enable it.
build: From a command prompt with the VC tools available (See the
instructions for OpenSSL build above for help on starting the
proper command prompt in RELEASE mode):
- C:\...\> cd C:\cygwin\opt\local\pgm\wxMSW-3.0.2\build\msw
+ C:\...\> cd <path\to\pgm>\wxMSW-3.0.2\build\msw
C:\...\> nmake BUILD=release SHARED=0 DIR_SUFFIX_CPU= -f makefile.vc
Or - if building a 64bit version:
- C:\...\> cd C:\cygwin\opt\local\pgm\wxMSW-3.0.2\build\msw
+ C:\...\> cd <path\to\pgm>\wxMSW-3.0.2\build\msw
C:\...\> nmake TARGET_CPU=amd64 BUILD=release SHARED=0 DIR_SUFFIX_CPU= -f makefile.vc
-* The Erlang source distribution (from <http://www.erlang.org/download.html>).
- The same as for Unix platforms. Preferably use tar from within Cygwin to
+* Get the Erlang source distribution (from <http://www.erlang.org/download.html>).
+ The same as for Unix platforms. Preferably use tar from within Cygwin, MSYS or MSYS2 to
unpack the source tar.gz (`tar zxf otp_src_%OTP-REL%.tar.gz`).
- set the environment `ERL_TOP` to point to the root directory of the
+ Set the environment `ERL_TOP` to point to the root directory of the
source distribution. Let's say I stood in `$HOME/src` and unpacked
`otp_src_%OTP-REL%.tar.gz`, I then add the following to `.profile`:
ERL_TOP=$HOME/src/otp_src_%OTP-REL%
export $ERL_TOP
-* The TCL/TK binaries. You could compile Tcl/Tk for windows yourself,
- but you can get a stripped down version from our website which is
- suitable to include in the final binary package. If you want to supply
- tcl/tk yourself, read the instructions about how the tcl/tk tar file
- used in the build is constructed under `$ERL_TOP/lib/gs/tcl`. The easy
- way is to download <http://www.erlang.org/download/tcltk85_win32_bin.tar.gz>
- and unpack it standing in the `$ERL_TOP` directory. This will create the
- file `win32.tar.gz` in `$ERL_TOP/lib/gs/tcl/binaries`.
-
- One last alternative is to create a file named `SKIP` in the
- `$ERL_TOP/lib/gs/` after configure is run, but that will give you an
- erlang system without gs (which might be okay as you probably will use
- wx anyway).
-
- Note that there is no special 64bit version of TCL/TK needed, you
- can use the 32bit program even for a 64bit build.
The Shell Environment
---------------------
@@ -726,37 +687,18 @@ be easy after this. You could run `./otp_build env_win32` without
sets seems OK. The path is cleaned of spaces if possible (using DOS
style short names instead), the variables `OVERRIDE_TARGET`, `CC`, `CXX`,
`AR` and `RANLIB` are set to their respective wrappers and the directories
-`$ERL_TOP/erts/etc/win32/cygwin_tools/vc` and
-`$ERL_TOP/erts/etc/win32/cygwin_tool` are added first in the PATH.
-
-Try now a `type erlc`. That should result in the erlc wrapper script
-(which does not have the .sh extension, for reasons best kept
-untold...). It should reside in `$ERL_TOP/erts/etc/win32/cygwin_tools`
-or `$ERL_TOP/erts/etc/win32/msys_tools`. You could also try `which
-cc.sh`, which `ar.sh` etc.
+`$ERL_TOP/erts/etc/win32/<cygwin/msys>_tools/vc` and
+`$ERL_TOP/erts/etc/win32/<cygwin/msys>_tool` are added first in the PATH.
-Now you're ready to build...
+Now you can check which erlc you have by writing `type erlc` in your shell.
+It should reside in `$ERL_TOP/erts/etc/win32/cygwin_tools`
+or `$ERL_TOP/erts/etc/win32/msys_tools`.
Building and Installing
-----------------------
-Now it's assumed that you have executed `` eval `./otp_build env_win32` `` or
-`` eval `./otp_build env_win32 x64` `` for this particular shell...
-
-Building is easiest using the `otp_build` script. That script takes care
-of running configure, bootstrapping etc on Windows in a simple
-way. The `otp_build` script is the utility we use ourselves to build on
-different platforms and it therefore contains code for all sorts of
-platforms. The principle is, however, that for non-Unix platforms, one
-uses `./otp_build env_<target>` to set up environment and then the
-script knows how to build on the platform "by itself". You've already
-run `./otp_build env_win32` in the step above, so now it's mostly like
-we build on any platform. OK, here are then steps; Assuming you will
-want to build a full installation executable with NSIS, you can omit
-`<installation directory>` and the release will be copied to
-`$ERL_TOP/release/win32`: and there is where the packed self installing
-executable will reside too.
+Building is easiest using the `otp_build` script:
$ ./otp_build autoconf # Ignore the warning blob about versions of autoconf
$ ./otp_build configure <optional configure options>
@@ -764,18 +706,18 @@ executable will reside too.
$ ./otp_build release -a <installation directory>
$ ./otp_build installer_win32 <installation directory> # optional
-Now you will have a file called `otp_win32_R12B.exe` in the
-`<installation directory>`, i.e. `$ERL_TOP/release/win32`.
+Now you will have a file called `otp_win32_%OTP-REL%.exe` or `otp_win64_%OTP-REL%.exe`
+in the `<installation directory>`, i.e. `$ERL_TOP/release/win32`.
Lets get into more detail:
1. `$ ./otp_build autoconf` - This step rebuilds the configure scripts
- to work correctly in the cygwin environment. In an ideal world, this
+ to work correctly in your environment. In an ideal world, this
would not be needed, but alas, we have encountered several
incompatibilities between our distributed configure scripts (generated
- on a Linux platform) and the cygwin environment over the
- years. Running autoconf on cygwin ensures that the configure scripts
- are generated in a cygwin-compatible way and that they will work well
+ on a Linux platform) and the Cygwin/MSYS/MSYS2 environment over the
+ years. Running autoconf in Cygwin/MSYS/MSYS2 ensures that the configure
+ scripts are generated in a compatible way and that they will work well
in the next step.
2. `$ ./otp_build configure` - This runs the newly generated configure
@@ -784,38 +726,21 @@ Lets get into more detail:
this awkward target name and behave accordingly. The CC variable also
makes the compiler be `cc.sh`, which wraps MSVC++, so all configure
tests regarding the C compiler gets to run the right compiler. A lot of
- the tests are not needed on Windows, but I thought it best to run the
- whole configure anyway. The only configure option you might want to
- supply is `--with-ssl`, which might be needed if you have built your
- own OpenSSL distribution. The Shining Lights distribution should be
- found automatically by `configure`, if that fails, add a
- `--with-ssl=<dir>` that specifies the root directory of your OpenSSL
- installation.
+ the tests are not needed on Windows, but we thought it best to run the
+ whole configure anyway.
3. `$ ./otp_build boot -a` - This uses the bootstrap directory (shipped
with the source, `$ERL_TOP/bootstrap`) to build a complete OTP
- system. It first builds an emulator and sets up a minimal OTP system
- under `$ERL_TOP/bootstrap`, then starts to compile the different OTP
- compilers to make the `$ERL_TOP/bootstrap` system potent enough to be
- able to compile all Erlang code in OTP. Then, all Erlang and C code
- under `$ERL_TOP/lib` is built using the bootstrap system, giving a
- complete OTP system (although not installed). When this is done, one
- can run Erlang from within the source tree, just type `$ERL_TOP/bin/erl`
- and you should have a prompt. If you omit the -a flag, you'll get a
- smaller system, that might be useful during development. Now
- exit from Erlang and start making a release of the thing:
+ system. When this is done you can run erl from within the source tree;
+ just type `$ERL_TOP/bin/erl` and you whould have the prompt.
4. `$ ./otp_build release -a` - Builds a commercial release tree from the
- source tree, default is to put it in `$ERL_TOP/release/win32`, you can
+ source tree. The default is to put it in `$ERL_TOP/release/win32`. You can
give any directory as parameter (Cygwin style), but it doesn't really
- matter if you're going to build a self extracting installer too. You
- could of course build release to the final directory and then run
- `./Install.exe` standing in the directory where the release was put,
- that will create a fully functional OTP installation. But let's make
- the nifty installer:
-
-5. `$ ./otp_build installer_win32` - Create the self extracting installer
- executable. The executable `otp_win32_%OTP-REL%.exe` will be placed
+ matter if you're going to build a self extracting installer too.
+
+5. `$ ./otp_build installer_win32` - Creates the self extracting installer executable.
+ The executable `otp_win32_%OTP-REL%.exe` or `otp_win64_%OTP-REL%.exe` will be placed
in the top directory of the release created in the previous step. If
no release directory is specified, the release is expected to have
been built to `$ERL_TOP/release/win32`, which also will be the place
@@ -824,7 +749,7 @@ Lets get into more detail:
/tmp/erl_release`), you're expected to give the same parameter here,
(i.e. `./otp_build installer_win32 /tmp/erl_release`). You need to have
a full NSIS installation and `makensis.exe` in your path for this to
- work of course. Once you have created the installer, you can run it to
+ work. Once you have created the installer, you can run it to
install Erlang/OTP in the regular way, just run the executable and
follow the steps in the installation wizard. To get all default settings
in the installation without any questions asked, you run the executable
@@ -844,37 +769,17 @@ Lets get into more detail:
and after a while Erlang/OTP-%OTP-REL% will have been installed in
`C:\Program Files\erl%ERTS-VSN%\`, with shortcuts in the menu etc.
- The necessary setup of an Erlang installation is actually done by the
- program `Install.exe`, which resides in the release top. That program
- creates `.ini`-files and copies the correct boot scripts. If one has
- the correct directory tree (like after a `./otp_build release -a`), only
- the running of `Install.exe` is necessary to get a fully functional
- OTP. What the self extracting installer adds is (of course) the
- possibility to distribute the binary easily, together with adding
- shortcuts to the Windows start menu. There is also some adding of
- entries in the registry, to associate `.erl` and `.beam` files with
- Erlang and get nifty icons, but that's not something you'll really need
- to run Erlang. The registry is also used to store uninstall information,
- but if one has not used the self extracting installer, one cannot
- (need not) do any uninstall, one just scratches the release directory
- and everything is gone. Erlang/OTP does not *need* to put anything
- in the Windows registry at all, and does not if you don't use the self
- extracting installer. In other words the installer is pure cosmetics.
-
-> *NOTE*: Beginning with R9C, the Windows installer does *not* add Erlang
-> to the system wide path. If one wants to have Erlang in the path, one
-> has to add it by hand.
Development
-----------
Once the system is built, you might want to change it. Having a test
-release in some nice directory might be useful, but you also can run
+release in some nice directory might be useful, but you can also run
Erlang from within the source tree. The target `local_setup`, makes
the program `$ERL_TOP/bin/erl.exe` usable and it also uses all the OTP
libraries in the source tree.
-If you hack the emulator, you can then build the emulator executable
+If you hack the emulator, you can build the emulator executable
by standing in `$ERL_TOP/erts/emulator` and do a simple
$ make opt
@@ -923,12 +828,12 @@ or even in the source directory...
$ cd $ERL_TOP/lib/stdlib/src
$ make opt
-Note that you're expected o have a fresh Erlang in your path when
+Note that you're expected to have a fresh Erlang in your path when
doing this, preferably the plain %OTP-REL% you have built in the previous
steps. You could also add `$ERL_TOP/bootstrap/bin` to your `PATH` before
-rebuilding specific libraries, that would give you a good enough
+rebuilding specific libraries. That would give you a good enough
Erlang system to compile any OTP erlang code. Setting up the path
-correctly is a little bit tricky, you still need to have
+correctly is a little bit tricky. You still need to have
`$ERL_TOP/erts/etc/win32/cygwin_tools/vc` and
`$ERL_TOP/erts/etc/win32/cygwin_tools` *before* the actual emulator
in the path. A typical setting of the path for using the bootstrap
@@ -963,57 +868,27 @@ Remember that:
That's basically all you need to get going.
+
Using GIT
---------
-You might want to check out versions of the source code from GitHUB. That is possible directly in cygwin, but not in Msys. There is a project MsysGIT:
+You might want to check out versions of the source code from GitHUB. That is possible directly in Cygwin, but not in MSYS. There is a project MsysGIT:
URL:<http://code.google.com/p/msysgit/>
that makes a nice Git port. The msys prompt you get from MsysGIT is
however not compatible with the full version from MinGW, so you will
need to check out files using MsysGIT's command prompt and then switch
-to a common Msys command prompt for building. Also all test suites
-cannot be built as MsysGIT/Msys does not handle symbolic links. To
-build test suites on Windows, you will need Cygwin for now. Hopefully
-all symbolic links will disappear from our repository soon and this
-issue will disappear.
+to a common MSYS command prompt for building. Also all test suites
+cannot be built as MsysGIT/MSYS does not handle symbolic links.
-Final Words
------------
-My hope is that the possibility to build the whole system on Windows
-will open up for free development on this platform too. There are many
-things one might want to do better in the Windows version, like the
-window-style command prompt as well as pure Cygwin porting. Although i
-realize it's a much larger step to start building on Windows (with all
-the software you need) than for instance on Linux, I sincerely hope
-that some of you will make the effort and start submitting Windows
-friendly patches.
-
-The first build system for Erlang using Cygwin on Windows was created
-by Per Bergkvist. I haven't used his build system, but it's rumored to
-be good. The idea to do this came from his work, so credit is well
-deserved.
-
-Of course this would have been completely impossible without the
-excellent Cygwin. The guys at Cygnus solutions and
-Redhat deserve a huge THANKS! as well as all the other people in the
-free software community who have helped in creating the magnificent
-software that constitutes Cygwin.
-
-Also the people developing the alternative command prompt Msys and
-the MinGW compiler are worth huge THANKS! The 64bit port would have
-been impossible without the 64bit MinGW compiler.
-
-Good luck and Happy Hacking,
-Patrik, OTP
Copyright and License
---------------------
%CopyrightBegin%
-Copyright Ericsson AB 2003-2014. All Rights Reserved.
+Copyright Ericsson AB 2003-2015. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -1030,6 +905,8 @@ limitations under the License.
%CopyrightEnd%
- [1]: http://www.erlang.org/faq.html "mailing lists"
+ [1]: http://www.erlang.org/static/doc/mailinglist.html
+ [2]: http://bugs.erlang.org
+ [3]: https://github.com/erlang/otp
[?TOC]: true
diff --git a/bootstrap/lib/compiler/ebin/beam_a.beam b/bootstrap/lib/compiler/ebin/beam_a.beam
index 599f9cb073..2388ccad80 100644
--- a/bootstrap/lib/compiler/ebin/beam_a.beam
+++ b/bootstrap/lib/compiler/ebin/beam_a.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_asm.beam b/bootstrap/lib/compiler/ebin/beam_asm.beam
index 3656edb0a0..0e05b1474a 100644
--- a/bootstrap/lib/compiler/ebin/beam_asm.beam
+++ b/bootstrap/lib/compiler/ebin/beam_asm.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_bs.beam b/bootstrap/lib/compiler/ebin/beam_bs.beam
index 0823cb2dd7..18b9f8bc1b 100644
--- a/bootstrap/lib/compiler/ebin/beam_bs.beam
+++ b/bootstrap/lib/compiler/ebin/beam_bs.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_dict.beam b/bootstrap/lib/compiler/ebin/beam_dict.beam
index 1576d1bb8f..4e12260e65 100644
--- a/bootstrap/lib/compiler/ebin/beam_dict.beam
+++ b/bootstrap/lib/compiler/ebin/beam_dict.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_disasm.beam b/bootstrap/lib/compiler/ebin/beam_disasm.beam
index 5c2308ef9d..b2fd7faa0c 100644
--- a/bootstrap/lib/compiler/ebin/beam_disasm.beam
+++ b/bootstrap/lib/compiler/ebin/beam_disasm.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_validator.beam b/bootstrap/lib/compiler/ebin/beam_validator.beam
index 03582d94c3..73fa117755 100644
--- a/bootstrap/lib/compiler/ebin/beam_validator.beam
+++ b/bootstrap/lib/compiler/ebin/beam_validator.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/cerl_trees.beam b/bootstrap/lib/compiler/ebin/cerl_trees.beam
index 76b19363e9..7233eee9de 100644
--- a/bootstrap/lib/compiler/ebin/cerl_trees.beam
+++ b/bootstrap/lib/compiler/ebin/cerl_trees.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/compile.beam b/bootstrap/lib/compiler/ebin/compile.beam
index 8f60633c81..8126046e08 100644
--- a/bootstrap/lib/compiler/ebin/compile.beam
+++ b/bootstrap/lib/compiler/ebin/compile.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/rec_env.beam b/bootstrap/lib/compiler/ebin/rec_env.beam
index 69d3f62ca0..9388b5d4e1 100644
--- a/bootstrap/lib/compiler/ebin/rec_env.beam
+++ b/bootstrap/lib/compiler/ebin/rec_env.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/sys_core_dsetel.beam b/bootstrap/lib/compiler/ebin/sys_core_dsetel.beam
index 10df50e1e5..0c2d05286a 100644
--- a/bootstrap/lib/compiler/ebin/sys_core_dsetel.beam
+++ b/bootstrap/lib/compiler/ebin/sys_core_dsetel.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/sys_core_fold.beam b/bootstrap/lib/compiler/ebin/sys_core_fold.beam
index 809de44217..c510dfde01 100644
--- a/bootstrap/lib/compiler/ebin/sys_core_fold.beam
+++ b/bootstrap/lib/compiler/ebin/sys_core_fold.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/sys_pre_expand.beam b/bootstrap/lib/compiler/ebin/sys_pre_expand.beam
index d82f802bd7..71d381b5b3 100644
--- a/bootstrap/lib/compiler/ebin/sys_pre_expand.beam
+++ b/bootstrap/lib/compiler/ebin/sys_pre_expand.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/v3_kernel.beam b/bootstrap/lib/compiler/ebin/v3_kernel.beam
index d451819f19..b3f927ab3c 100644
--- a/bootstrap/lib/compiler/ebin/v3_kernel.beam
+++ b/bootstrap/lib/compiler/ebin/v3_kernel.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/code_server.beam b/bootstrap/lib/kernel/ebin/code_server.beam
index 22ae0e7ce6..ece4263caa 100644
--- a/bootstrap/lib/kernel/ebin/code_server.beam
+++ b/bootstrap/lib/kernel/ebin/code_server.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/erts_debug.beam b/bootstrap/lib/kernel/ebin/erts_debug.beam
index d1a60d5cd9..908c63cb9a 100644
--- a/bootstrap/lib/kernel/ebin/erts_debug.beam
+++ b/bootstrap/lib/kernel/ebin/erts_debug.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/file_io_server.beam b/bootstrap/lib/kernel/ebin/file_io_server.beam
index f29483ef36..dabb6b194e 100644
--- a/bootstrap/lib/kernel/ebin/file_io_server.beam
+++ b/bootstrap/lib/kernel/ebin/file_io_server.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/global.beam b/bootstrap/lib/kernel/ebin/global.beam
index 469859fa03..419102e285 100644
--- a/bootstrap/lib/kernel/ebin/global.beam
+++ b/bootstrap/lib/kernel/ebin/global.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet.beam b/bootstrap/lib/kernel/ebin/inet.beam
index 6353e6564b..55598b0067 100644
--- a/bootstrap/lib/kernel/ebin/inet.beam
+++ b/bootstrap/lib/kernel/ebin/inet.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet_db.beam b/bootstrap/lib/kernel/ebin/inet_db.beam
index 8b6273610c..1b7450f0d3 100644
--- a/bootstrap/lib/kernel/ebin/inet_db.beam
+++ b/bootstrap/lib/kernel/ebin/inet_db.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/user.beam b/bootstrap/lib/kernel/ebin/user.beam
index 5b07718039..c2b2808555 100644
--- a/bootstrap/lib/kernel/ebin/user.beam
+++ b/bootstrap/lib/kernel/ebin/user.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/beam_lib.beam b/bootstrap/lib/stdlib/ebin/beam_lib.beam
index 67aeb1a587..9ad11640b5 100644
--- a/bootstrap/lib/stdlib/ebin/beam_lib.beam
+++ b/bootstrap/lib/stdlib/ebin/beam_lib.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/epp.beam b/bootstrap/lib/stdlib/ebin/epp.beam
index 6a585f8a08..d9cd838ca9 100644
--- a/bootstrap/lib/stdlib/ebin/epp.beam
+++ b/bootstrap/lib/stdlib/ebin/epp.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/erl_lint.beam b/bootstrap/lib/stdlib/ebin/erl_lint.beam
index 8c07c78369..21b7ce4f3a 100644
--- a/bootstrap/lib/stdlib/ebin/erl_lint.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_lint.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/erl_pp.beam b/bootstrap/lib/stdlib/ebin/erl_pp.beam
index d97b5e075b..4cc4884c92 100644
--- a/bootstrap/lib/stdlib/ebin/erl_pp.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_pp.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/io.beam b/bootstrap/lib/stdlib/ebin/io.beam
index 1f2a113fdd..283c912800 100644
--- a/bootstrap/lib/stdlib/ebin/io.beam
+++ b/bootstrap/lib/stdlib/ebin/io.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/otp_internal.beam b/bootstrap/lib/stdlib/ebin/otp_internal.beam
index 97b7826149..9b1bd2c77b 100644
--- a/bootstrap/lib/stdlib/ebin/otp_internal.beam
+++ b/bootstrap/lib/stdlib/ebin/otp_internal.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/rand.beam b/bootstrap/lib/stdlib/ebin/rand.beam
index 588bbb3394..5bc835e2e8 100644
--- a/bootstrap/lib/stdlib/ebin/rand.beam
+++ b/bootstrap/lib/stdlib/ebin/rand.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/random.beam b/bootstrap/lib/stdlib/ebin/random.beam
index e1d62c98d5..fc351a800a 100644
--- a/bootstrap/lib/stdlib/ebin/random.beam
+++ b/bootstrap/lib/stdlib/ebin/random.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/shell.beam b/bootstrap/lib/stdlib/ebin/shell.beam
index e27b7bcb84..ee304db782 100644
--- a/bootstrap/lib/stdlib/ebin/shell.beam
+++ b/bootstrap/lib/stdlib/ebin/shell.beam
Binary files differ
diff --git a/configure.in b/configure.in
index e8c8680e19..51728a847e 100644
--- a/configure.in
+++ b/configure.in
@@ -278,6 +278,10 @@ AC_ARG_ENABLE(builtin-zlib,
AS_HELP_STRING([--enable-builtin-zlib],
[force use of our own built-in zlib]))
+AC_ARG_ENABLE(sharing-preserving,
+AS_HELP_STRING([--enable-sharing-preserving],
+ [enable copying of terms without destroying sharing]))
+
dnl This functionality has been lost along the way... :(
dnl It could perhaps be nice to reintroduce some day; therefore,
dnl it is not removed just commented out.
diff --git a/erts/aclocal.m4 b/erts/aclocal.m4
index eb7d0411a7..f6d8f20e4e 100644
--- a/erts/aclocal.m4
+++ b/erts/aclocal.m4
@@ -127,18 +127,18 @@ MIXED_MSYS=no
AC_MSG_CHECKING(for mixed cygwin or msys and native VC++ environment)
if test "X$host" = "Xwin32" -a "x$GCC" != "xyes"; then
- if test -x /usr/bin/cygpath; then
- CFLAGS="-O2"
- MIXED_CYGWIN=yes
- AC_MSG_RESULT([Cygwin and VC])
- MIXED_CYGWIN_VC=yes
- CPPFLAGS="$CPPFLAGS -DERTS_MIXED_CYGWIN_VC"
- elif test -x /usr/bin/msysinfo; then
+ if test -x /usr/bin/msys-?.0.dll; then
CFLAGS="-O2"
MIXED_MSYS=yes
AC_MSG_RESULT([MSYS and VC])
MIXED_MSYS_VC=yes
CPPFLAGS="$CPPFLAGS -DERTS_MIXED_MSYS_VC"
+ elif test -x /usr/bin/cygpath; then
+ CFLAGS="-O2"
+ MIXED_CYGWIN=yes
+ AC_MSG_RESULT([Cygwin and VC])
+ MIXED_CYGWIN_VC=yes
+ CPPFLAGS="$CPPFLAGS -DERTS_MIXED_CYGWIN_VC"
else
AC_MSG_RESULT([undeterminable])
AC_MSG_ERROR(Seems to be mixed windows but not with cygwin, cannot handle this!)
diff --git a/erts/configure.in b/erts/configure.in
index 32d8bca98c..20075b08c9 100644
--- a/erts/configure.in
+++ b/erts/configure.in
@@ -787,6 +787,18 @@ esac
AC_SUBST(LIBCARBON)
+dnl Check if we should/can build a sharing-preserving emulator
+
+AC_MSG_CHECKING(if we are building a sharing-preserving emulator)
+if test "$enable_sharing_preserving" = "yes"; then
+ AC_DEFINE(SHCOPY, [1],
+ [Define if building a sharing-preserving emulator])
+ AC_MSG_RESULT([yes])
+else
+ AC_MSG_RESULT([no])
+fi
+
+
dnl some tests below will call this if we haven't already - and autoconf
dnl can't handle those tests being done conditionally at runtime
AC_PROG_CPP
@@ -2068,8 +2080,7 @@ fi
case X$erl_xcomp_posix_memalign in
Xno) ;;
- Xyes) AC_DEFINE(HAVE_POSIX_MEMALIGN,[1],
- [Define to 1 if you have the `posix_memalign' function.]) ;;
+ Xyes) have_posix_memalign=yes ;;
*)
AC_CHECK_FUNC(
[posix_memalign],
@@ -2084,15 +2095,19 @@ int main(void) {
return error;
return 0;
}
-],AC_DEFINE(HAVE_POSIX_MEMALIGN,[1],
- [Define to 1 if you have the `posix_memalign' function.])
+],have_posix_memalign=yes
)
else
- AC_DEFINE(HAVE_POSIX_MEMALIGN,[1],
- [Define to 1 if you have the `posix_memalign' function.])
+ have_posix_memalign=yes
fi]);;
esac
+if test $have_posix_memalign = yes; then
+ AC_DEFINE(HAVE_POSIX_MEMALIGN,[1],
+ [Define to 1 if you have the `posix_memalign' function.])
+fi
+
+
dnl writev on OS X snow leopard is broken for files > 4GB
case $host_os in
darwin10.8.0)
@@ -3683,7 +3698,7 @@ dnl crypto
#
#--------------------------------------------------------------------
-DED_SYS_INCLUDE="-I${ERL_TOP}/erts/emulator/beam -I${ERL_TOP}/erts/include -I${ERL_TOP}/erts/include/$host -I${ERL_TOP}/erts/include/internal -I${ERL_TOP}/erts/include/internal/$host -I${ERL_TOP}/erts/emulator/sys/$ERLANG_OSTYPE"
+DED_SYS_INCLUDE="-I${ERL_TOP}/erts/emulator/beam -I${ERL_TOP}/erts/include -I${ERL_TOP}/erts/include/$host -I${ERL_TOP}/erts/include/internal -I${ERL_TOP}/erts/include/internal/$host -I${ERL_TOP}/erts/emulator/sys/$ERLANG_OSTYPE -I${ERL_TOP}/erts/emulator/sys/common"
if test "X$ETHR_DEFS" = "X"; then
DED_THR_DEFS="-D_THREAD_SAFE -D_REENTRANT"
diff --git a/erts/doc/src/absform.xml b/erts/doc/src/absform.xml
index 49fe784d06..1c0c3e1319 100644
--- a/erts/doc/src/absform.xml
+++ b/erts/doc/src/absform.xml
@@ -11,7 +11,7 @@
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
@@ -19,7 +19,7 @@
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-
+
</legalnotice>
<title>The Abstract Format</title>
@@ -35,24 +35,24 @@
<p></p>
<p>This document describes the standard representation of parse trees for Erlang
programs as Erlang terms. This representation is known as the <em>abstract format</em>.
- Functions dealing with such parse trees are <c><![CDATA[compile:forms/[1,2]]]></c>
+ Functions dealing with such parse trees are <c>compile:forms/[1,2]</c>
and functions in the modules
- <c><![CDATA[epp]]></c>,
- <c><![CDATA[erl_eval]]></c>,
- <c><![CDATA[erl_lint]]></c>,
- <c><![CDATA[erl_pp]]></c>,
- <c><![CDATA[erl_parse]]></c>,
+ <c>epp</c>,
+ <c>erl_eval</c>,
+ <c>erl_lint</c>,
+ <c>erl_pp</c>,
+ <c>erl_parse</c>,
and
- <c><![CDATA[io]]></c>.
+ <c>io</c>.
They are also used as input and output for parse transforms (see the module
- <c><![CDATA[compile]]></c>).</p>
- <p>We use the function <c><![CDATA[Rep]]></c> to denote the mapping from an Erlang source
- construct <c><![CDATA[C]]></c> to its abstract format representation <c><![CDATA[R]]></c>, and write
- <c><![CDATA[R = Rep(C)]]></c>.
+ <c>compile</c>).</p>
+ <p>We use the function <c>Rep</c> to denote the mapping from an Erlang source
+ construct <c>C</c> to its abstract format representation <c>R</c>, and write
+ <c>R = Rep(C)</c>.
</p>
- <p>The word <c><![CDATA[LINE]]></c> below represents an integer, and denotes the
+ <p>The word <c>LINE</c> below represents an integer, and denotes the
number of the line in the source file where the construction occurred.
- Several instances of <c><![CDATA[LINE]]></c> in the same construction may denote
+ Several instances of <c>LINE</c> in the same construction may denote
different lines.</p>
<p>Since operators are not terms in their own right, when operators are
mentioned below, the representation of an operator should be taken to
@@ -61,227 +61,111 @@
</p>
<section>
- <title>Module declarations and forms</title>
+ <title>Module Declarations and Forms</title>
<p>A module declaration consists of a sequence of forms that are either
function declarations or attributes.</p>
<list type="bulleted">
<item>If D is a module declaration consisting of the forms
- <c><![CDATA[F_1]]></c>, ..., <c><![CDATA[F_k]]></c>, then
- Rep(D) = <c><![CDATA[[Rep(F_1), ..., Rep(F_k)]]]></c>.</item>
- <item>If F is an attribute <c><![CDATA[-module(Mod)]]></c>, then
- Rep(F) = <c><![CDATA[{attribute,LINE,module,Mod}]]></c>.</item>
- <item>If F is an attribute <c><![CDATA[-behavior(Behavior)]]></c>, then
- Rep(F) = <c><![CDATA[{attribute,LINE,behavior,Behavior}]]></c>.</item>
- <item>If F is an attribute <c><![CDATA[-behaviour(Behaviour)]]></c>, then
- Rep(F) = <c><![CDATA[{attribute,LINE,behaviour,Behaviour}]]></c>.</item>
- <item>If F is an attribute <c><![CDATA[-export([Fun_1/A_1, ..., Fun_k/A_k])]]></c>, then
- Rep(F) = <c><![CDATA[{attribute,LINE,export,[{Fun_1,A_1}, ..., {Fun_k,A_k}]}]]></c>.</item>
- <item>If F is an attribute <c><![CDATA[-import(Mod,[Fun_1/A_1, ..., Fun_k/A_k])]]></c>, then
- Rep(F) = <c><![CDATA[{attribute,LINE,import,{Mod,[{Fun_1,A_1}, ..., {Fun_k,A_k}]}}]]></c>.</item>
- <item>If F is an attribute <c><![CDATA[-compile(Options)]]></c>, then
- Rep(F) = <c><![CDATA[{attribute,LINE,compile,Options}]]></c>.</item>
- <item>If F is an attribute <c><![CDATA[-file(File,Line)]]></c>, then
- Rep(F) = <c><![CDATA[{attribute,LINE,file,{File,Line}}]]></c>.</item>
- <item>If F is a record declaration <c><![CDATA[-record(Name,{V_1, ..., V_k})]]></c>, then
- Rep(F) =
- <c><![CDATA[{attribute,LINE,record,{Name,[Rep(V_1), ..., Rep(V_k)]}}]]></c>. For Rep(V), see below.</item>
- <item>If F is a type attribute (i.e. <c><![CDATA[opaque]]></c> or
- <c><![CDATA[type]]></c>)
- <c><![CDATA[-Attr Name(A_1, ..., A_k) :: T]]></c> where each
- <c><![CDATA[A_i]]></c> is a variable, then Rep(F) =
- <c><![CDATA[{attribute,LINE,Attr,{Name,Rep(T),[Rep(A_1), ..., Rep(A_k)]}}]]></c>.
- For Rep(T), see below.</item>
- <item>If F is a type spec (i.e. <c><![CDATA[callback]]></c> or
- <c><![CDATA[spec]]></c>)
- <c><![CDATA[-Attr F Tc_1; ...; Tc_k]]></c>,
- where each <c><![CDATA[Tc_i]]></c> is a fun type clause with an
- argument sequence of the same length <c><![CDATA[Arity]]></c>, then
- Rep(F) =
- <c><![CDATA[{Attr,LINE,{{F,Arity},[Rep(Tc_1), ..., Rep(Tc_k)]}}]]></c>.
- For Rep(Tc_i), see below.</item>
- <item>If F is a type spec (i.e. <c><![CDATA[callback]]></c> or
- <c><![CDATA[spec]]></c>)
- <c><![CDATA[-Attr Mod:F Tc_1; ...; Tc_k]]></c>,
- where each <c><![CDATA[Tc_i]]></c> is a fun type clause with an
- argument sequence of the same length <c><![CDATA[Arity]]></c>, then
- Rep(F) =
- <c><![CDATA[{Attr,LINE,{{Mod,F,Arity},[Rep(Tc_1), ..., Rep(Tc_k)]}}]]></c>.
- For Rep(Tc_i), see below.</item>
- <item>If F is a wild attribute <c><![CDATA[-A(T)]]></c>, then
- Rep(F) = <c><![CDATA[{attribute,LINE,A,T}]]></c>.
+ <c>F_1</c>, ..., <c>F_k</c>, then
+ Rep(D) = <c>[Rep(F_1), ..., Rep(F_k)]</c>.</item>
+ <item>If F is an attribute <c>-module(Mod)</c>, then
+ Rep(F) = <c>{attribute,LINE,module,Mod}</c>.</item>
+ <item>If F is an attribute <c>-behavior(Behavior)</c>, then
+ Rep(F) = <c>{attribute,LINE,behavior,Behavior}</c>.</item>
+ <item>If F is an attribute <c>-behaviour(Behaviour)</c>, then
+ Rep(F) = <c>{attribute,LINE,behaviour,Behaviour}</c>.</item>
+ <item>If F is an attribute <c>-export([Fun_1/A_1, ..., Fun_k/A_k])</c>, then
+ Rep(F) = <c>{attribute,LINE,export,[{Fun_1,A_1}, ..., {Fun_k,A_k}]}</c>.</item>
+ <item>If F is an attribute <c>-import(Mod,[Fun_1/A_1, ..., Fun_k/A_k])</c>, then
+ Rep(F) = <c>{attribute,LINE,import,{Mod,[{Fun_1,A_1}, ..., {Fun_k,A_k}]}}</c>.</item>
+ <item>If F is an attribute <c>-export_type([Type_1/A_1, ..., Type_k/A_k])</c>, then
+ Rep(F) = <c>{attribute,LINE,export_type,[{Type_1,A_1}, ..., {Type_k,A_k}]}</c>.</item>
+ <item>If F is an attribute <c>-compile(Options)</c>, then
+ Rep(F) = <c>{attribute,LINE,compile,Options}</c>.</item>
+ <item>If F is an attribute <c>-file(File,Line)</c>, then
+ Rep(F) = <c>{attribute,LINE,file,{File,Line}}</c>.</item>
+ <item>If F is a record declaration
+ <c>-record(Name,{V_1, ..., V_k})</c>, then Rep(F) =
+ <c>{attribute,LINE,record,{Name,[Rep(V_1), ..., Rep(V_k)]}}</c>.
+ For Rep(V), see below.</item>
+ <item>If F is a type declaration
+ <c>-Type Name(V_1, ..., V_k) :: T</c>, where
+ <c>Type</c> is either the atom <c>type</c> or the atom <c>opaque</c>,
+ each <c>V_i</c> is a variable, and <c>T</c> is a type, then Rep(F) =
+ <c>{attribute,LINE,Type,{Name,Rep(T),[Rep(V_1), ..., Rep(V_k)]}}</c>.
+ </item>
+ <item>If F is a function specification
+ <c>-Spec Name Ft_1; ...; Ft_k</c>,
+ where <c>Spec</c> is either the atom <c>spec</c> or the atom
+ <c>callback</c>, and each <c>Ft_i</c> is a possibly constrained
+ function type with an argument sequence of the same length
+ <c>Arity</c>, then Rep(F) =
+ <c>{attribute,Line,Spec,{{Name,Arity},[Rep(Ft_1), ..., Rep(Ft_k)]}}</c>.
+ </item>
+ <item>If F is a function specification
+ <c>-spec Mod:Name Ft_1; ...; Ft_k</c>,
+ where each <c>Ft_i</c> is a possibly constrained
+ function type with an argument sequence of the same length
+ <c>Arity</c>, then Rep(F) =
+ <c>{attribute,Line,spec,{{Mod,Name,Arity},[Rep(Ft_1), ..., Rep(Ft_k)]}}</c>.
+ </item>
+ <item>If F is a wild attribute <c>-A(T)</c>, then
+ Rep(F) = <c>{attribute,LINE,A,T}</c>.
<br></br></item>
- <item>If F is a function declaration <c><![CDATA[Name Fc_1 ; ... ; Name Fc_k]]></c>,
- where each <c><![CDATA[Fc_i]]></c> is a function clause with a
- pattern sequence of the same length <c><![CDATA[Arity]]></c>, then
- Rep(F) = <c><![CDATA[{function,LINE,Name,Arity,[Rep(Fc_1), ...,Rep(Fc_k)]}]]></c>.</item>
+ <item>If F is a function declaration
+ <c>Name Fc_1 ; ... ; Name Fc_k</c>,
+ where each <c>Fc_i</c> is a function clause with a
+ pattern sequence of the same length <c>Arity</c>, then
+ Rep(F) = <c>{function,LINE,Name,Arity,[Rep(Fc_1), ...,Rep(Fc_k)]}</c>.
+ </item>
</list>
<section>
- <title>Type clauses</title>
- <list type="bulleted">
- <item>If T is a fun type clause
- <c><![CDATA[(A_1, ..., A_n) -> Ret]]></c>, where each
- <c><![CDATA[A_i]]></c> and <c><![CDATA[Ret]]></c> are types, then
- Rep(T) =
- <c><![CDATA[{type,LINE,'fun',[{type,LINE,product,[Rep(A_1), ..., Rep(A_n)]},Rep(Ret)]}]]></c>.
- </item>
- <item>If T is a bounded fun type clause <c><![CDATA[Tc when Tg]]></c>,
- where <c><![CDATA[Tc]]></c> is an unbounded fun type clause and
- <c><![CDATA[Tg]]></c> is a type guard sequence, then Rep(T) =
- <c><![CDATA[{type,LINE,bounded_fun,[Rep(Tc),Rep(Tg)]}]]></c>.</item>
- </list>
- </section>
-
- <section>
- <title>Type guards</title>
- <list type="bulleted">
- <item>If G is a constraint <c><![CDATA[F(A_1, ..., A_k)]]></c>, where
- <c><![CDATA[F]]></c> is an atom and each <c><![CDATA[A_i]]></c> is a
- type, then Rep(G) =
- <c><![CDATA[{type,LINE,constraint,[Rep(F),[Rep(A_1), ..., Rep(A_k)]]}]]></c>.
- </item>
- <item>If G is a type definition <c><![CDATA[Name :: Type]]></c>,
- where <c><![CDATA[Name]]></c> is a variable and
- <c><![CDATA[Type]]></c> is a type, then Rep(G) =
- <c><![CDATA[{type,LINE,constraint,[{atom,LINE,is_subtype},[Rep(Name),Rep(Type)]]}]]></c>.</item>
- </list>
- </section>
-
- <section>
- <title>Types</title>
- <list type="bulleted">
- <item>If T is a type definition <c><![CDATA[Name :: Type]]></c>,
- where <c><![CDATA[Name]]></c> is a variable and
- <c><![CDATA[Type]]></c> is a type, then Rep(T) =
- <c><![CDATA[{ann_type,LINE,[Rep(Name),Rep(Type)]}]]></c>.</item>
- <item>If T is a type union <c><![CDATA[A_1 | ... | A_k]]></c>,
- where each <c><![CDATA[A_i]]></c> is a type, then Rep(T) =
- <c><![CDATA[{type,LINE,union,[Rep(A_1), ..., Rep(A_k)]}]]></c>.</item>
- <item>If T is a type range <c><![CDATA[L .. R]]></c>,
- where <c><![CDATA[L]]></c> and <c><![CDATA[R]]></c> are types, then
- Rep(T) = <c><![CDATA[{type,LINE,range,[Rep(L), Rep(R)]}]]></c>.</item>
- <item>If T is a binary operation <c><![CDATA[L Op R]]></c>,
- where <c><![CDATA[Op]]></c> is an arithmetic or bitwise binary operator
- and <c><![CDATA[L]]></c> and <c><![CDATA[R]]></c> are types, then
- Rep(T) = <c><![CDATA[{op,LINE,Op,Rep(L),Rep(R)}]]></c>.</item>
- <item>If T is <c><![CDATA[Op A]]></c>, where <c><![CDATA[Op]]></c> is an
- arithmetic or bitwise unary operator and <c><![CDATA[A]]></c> is a
- type, then Rep(T) = <c><![CDATA[{op,LINE,Op,Rep(A)}]]></c>.</item>
- <item>If T is a fun type <c><![CDATA[fun()]]></c>, then Rep(T) =
- <c><![CDATA[{type,LINE,'fun',[]}]]></c>.</item>
- <item>If T is a variable <c><![CDATA[V]]></c>, then Rep(T) =
- <c><![CDATA[{var,LINE,A}]]></c>, where <c><![CDATA[A]]></c> is an atom
- with a printname consisting of the same characters as
- <c><![CDATA[V]]></c>.</item>
- <item>If T is an atomic literal L and L is not a string literal, then
- Rep(T) = Rep(L).</item>
- <item>If T is a tuple or map type <c><![CDATA[F()]]></c> (i.e.
- <c><![CDATA[tuple]]></c> or <c><![CDATA[map]]></c>), then Rep(T) =
- <c><![CDATA[{type,LINE,F,any}]]></c>.</item>
- <item>If T is a type <c><![CDATA[F(A_1, ..., A_k)]]></c>, where each
- <c><![CDATA[A_i]]></c> is a type, then Rep(T) =
- <c><![CDATA[{user_type,LINE,F,[Rep(A_1), ..., Rep(A_k)]}]]></c>.</item>
- <item>If T is a remote type <c><![CDATA[M:F(A_1, ..., A_k)]]></c>, where
- each <c><![CDATA[A_i]]></c> is a type and <c><![CDATA[M]]></c> and
- <c><![CDATA[F]]></c>, then Rep(T) =
- <c><![CDATA[{remote_type,LINE,[Rep(M),Rep(F),[Rep(A_1), ..., Rep(A_k)]]}]]></c>.
- </item>
- <item>If T is the nil type <c><![CDATA[[]]]></c>, then Rep(T) =
- <c><![CDATA[{type,LINE,nil,[]}]]></c>.</item>
- <item>If T is a list type <c><![CDATA[[A]]]></c>, where
- <c><![CDATA[A]]></c> is a type, then Rep(T) =
- <c><![CDATA[{type,LINE,list,[Rep(A)]}]]></c>.</item>
- <item>If T is a non-empty list type <c><![CDATA[[A, ...]]]></c>, where
- <c><![CDATA[A]]></c> is a type, then Rep(T) =
- <c><![CDATA[{type,LINE,nonempty_list,[Rep(A)]}]]></c>.</item>
- <item>If T is a map type <c><![CDATA[#{P_1, ..., P_k}]]></c>, where each
- <c><![CDATA[P_i]]></c> is a map pair type, then Rep(T) =
- <c><![CDATA[{type,LINE,map,[Rep(P_1), ..., Rep(P_k)]}]]></c>.</item>
- <item>If T is a map pair type <c><![CDATA[K => V]]></c>, where
- <c><![CDATA[K]]></c> and <c><![CDATA[V]]></c> are types,
- then Rep(T) =
- <c><![CDATA[{type,LINE,map_field_assoc,[Rep(K),Rep(V)]}]]></c>.</item>
- <item>If T is a tuple type <c><![CDATA[{A_1, ..., A_k}]]></c>, where
- each <c><![CDATA[A_i]]></c> is a type, then Rep(T) =
- <c><![CDATA[{type,LINE,tuple,[Rep(A_1), ..., Rep(A_k)]}]]></c>.</item>
- <item>If T is a record type <c><![CDATA[#Name{}]]></c>, where
- <c><![CDATA[Name]]></c> is an atom, then Rep(T) =
- <c><![CDATA[{type,LINE,record,[Rep(Name)]}]]></c>.</item>
- <item>If T is a record type <c><![CDATA[#Name{F_1, ..., F_k}]]></c>,
- where <c><![CDATA[Name]]></c> is an atom, then Rep(T) =
- <c><![CDATA[{type,LINE,record,[Rep(Name),[Rep(F_1), ..., Rep(F_k)]]}]]></c>.
- </item>
- <item>If T is a record field type <c><![CDATA[Name :: Type]]></c>,
- where <c><![CDATA[Name]]></c> is an atom, then Rep(T) =
- <c><![CDATA[{type,LINE,field_type,[Rep(Name),Rep(Type)]}]]></c>.</item>
- <item>If T is a record field type <c><![CDATA[<<>>]]></c>, then Rep(T) =
- <c><![CDATA[{type,LINE,binary,[{integer,LINE,0},{integer,LINE,0}]}]]></c>.
- </item>
- <item>If T is a binary type <c><![CDATA[<< _ : B >>]]></c>, where
- <c><![CDATA[B]]></c> is a type, then Rep(T) =
- <c><![CDATA[{type,LINE,binary,[Rep(B),{integer,LINE,0}]}]]></c>.</item>
- <item>If T is a binary type <c><![CDATA[<< _ : _ * U >>]]></c>,
- where <c><![CDATA[U]]></c> is a type, then Rep(T) =
- <c><![CDATA[{type,LINE,binary,[{integer,LINE,0},Rep(U)]}]]></c>.</item>
- <item>If T is a binary type <c><![CDATA[<< _ : B , _ : _ * U >>]]></c>,
- where <c><![CDATA[B]]></c> and <c><![CDATA[U]]></c> is a type, then
- Rep(T) =
- <c><![CDATA[{type,LINE,binary,[Rep(B),Rep(U)]}]]></c>.</item>
-
- <item>If T is a fun type <c><![CDATA[fun((...) -> Ret)]]></c>, then
- Rep(T) = <c><![CDATA[{type,LINE,'fun',[{type,LINE,product,[]},Rep(Ret)]}]]></c>.
- </item>
- <item>If T is a fun type <c><![CDATA[fun(Tc)]]></c>, where
- <c><![CDATA[Tc]]></c> is an unbounded fun type clause,
- then Rep(T) = <c><![CDATA[Rep(Tc)]]></c>.</item>
- </list>
- </section>
-
- <section>
- <title>Record fields</title>
+ <title>Record Fields</title>
<p>Each field in a record declaration may have an optional
- explicit default initializer expression</p>
+ explicit default initializer expression, as well as an
+ optional type.</p>
<list type="bulleted">
- <item>If V is <c><![CDATA[A]]></c>, then
- Rep(V) = <c><![CDATA[{record_field,LINE,Rep(A)}]]></c>.</item>
- <item>If V is <c><![CDATA[A = E]]></c>, then
- Rep(V) = <c><![CDATA[{record_field,LINE,Rep(A),Rep(E)}]]></c>.</item>
- <item>If V is <c><![CDATA[A :: T]]></c>, where <c><![CDATA[A]]></c> is
- an atom and <c><![CDATA[T]]></c> is a type, then Rep(V) =
- <c><![CDATA[{typed_record_field,{record_field,LINE,Rep(A)},Rep(T)}]]></c>.
- </item>
- <item>If V is <c><![CDATA[A = E :: T]]></c>, where <c><![CDATA[A]]></c>
- is an atom, <c><![CDATA[E]]></c> is an expression and
- <c><![CDATA[T]]></c> is a type, then Rep(V) =
- <c><![CDATA[{typed_record_field,{record_field,LINE,Rep(A),Rep(E)},Rep(T)}]]></c>.
- </item>
+ <item>If V is <c>A</c>, then
+ Rep(V) = <c>{record_field,LINE,Rep(A)}</c>.</item>
+ <item>If V is <c>A = E</c>,
+ where <c>E</c> is an expression, then
+ Rep(V) = <c>{record_field,LINE,Rep(A),Rep(E)}</c>.</item>
+ <item>If V is <c>A :: T</c>, where <c>T</c> is a type, then Rep(V) =
+ <c>{typed_record_field,{record_field,LINE,Rep(A)},Rep(T)}</c>.
+ </item>
+ <item>If V is <c>A = E :: T</c>, where
+ <c>E</c> is an expression and <c>T</c> is a type, then Rep(V) =
+ <c>{typed_record_field,{record_field,LINE,Rep(A),Rep(E)},Rep(T)}</c>.
+ </item>
</list>
</section>
<section>
- <title>Representation of parse errors and end of file</title>
+ <title>Representation of Parse Errors and End-of-file</title>
<p>In addition to the representations of forms, the list that represents
- a module declaration (as returned by functions in <c><![CDATA[erl_parse]]></c> and
- <c><![CDATA[epp]]></c>) may contain tuples <c><![CDATA[{error,E}]]></c> and <c><![CDATA[{warning,W}]]></c>, denoting
- syntactically incorrect forms and warnings, and <c><![CDATA[{eof,LINE}]]></c>, denoting an end
- of stream encountered before a complete form had been parsed.</p>
+ a module declaration (as returned by functions in <c>erl_parse</c> and
+ <c>epp</c>) may contain tuples <c>{error,E}</c> and
+ <c>{warning,W}</c>, denoting syntactically incorrect forms and
+ warnings, and <c>{eof,LINE}</c>, denoting an end-of-stream
+ encountered before a complete form had been parsed.</p>
</section>
</section>
<section>
- <title>Atomic literals</title>
+ <title>Atomic Literals</title>
<p>There are five kinds of atomic literals, which are represented in the
same way in patterns, expressions and guards:</p>
<list type="bulleted">
<item>If L is an integer or character literal, then
- Rep(L) = <c><![CDATA[{integer,LINE,L}]]></c>.</item>
+ Rep(L) = <c>{integer,LINE,L}</c>.</item>
<item>If L is a float literal, then
- Rep(L) = <c><![CDATA[{float,LINE,L}]]></c>.</item>
+ Rep(L) = <c>{float,LINE,L}</c>.</item>
<item>If L is a string literal consisting of the characters
- <c><![CDATA[C_1]]></c>, ..., <c><![CDATA[C_k]]></c>, then
- Rep(L) = <c><![CDATA[{string,LINE,[C_1, ..., C_k]}]]></c>.</item>
+ <c>C_1</c>, ..., <c>C_k</c>, then
+ Rep(L) = <c>{string,LINE,[C_1, ..., C_k]}</c>.</item>
<item>If L is an atom literal, then
- Rep(L) = <c><![CDATA[{atom,LINE,L}]]></c>.</item>
+ Rep(L) = <c>{atom,LINE,L}</c>.</item>
</list>
<p>Note that negative integer and float literals do not occur as such; they are
parsed as an application of the unary negation operator.</p>
@@ -289,47 +173,47 @@
<section>
<title>Patterns</title>
- <p>If <c><![CDATA[Ps]]></c> is a sequence of patterns <c><![CDATA[P_1, ..., P_k]]></c>, then
- Rep(Ps) = <c><![CDATA[[Rep(P_1), ..., Rep(P_k)]]]></c>. Such sequences occur as the
+ <p>If <c>Ps</c> is a sequence of patterns <c>P_1, ..., P_k</c>, then
+ Rep(Ps) = <c>[Rep(P_1), ..., Rep(P_k)]</c>. Such sequences occur as the
list of arguments to a function or fun.</p>
<p>Individual patterns are represented as follows:</p>
<list type="bulleted">
<item>If P is an atomic literal L, then Rep(P) = Rep(L).</item>
- <item>If P is a compound pattern <c><![CDATA[P_1 = P_2]]></c>, then
- Rep(P) = <c><![CDATA[{match,LINE,Rep(P_1),Rep(P_2)}]]></c>.</item>
- <item>If P is a variable pattern <c><![CDATA[V]]></c>, then
- Rep(P) = <c><![CDATA[{var,LINE,A}]]></c>,
+ <item>If P is a compound pattern <c>P_1 = P_2</c>, then
+ Rep(P) = <c>{match,LINE,Rep(P_1),Rep(P_2)}</c>.</item>
+ <item>If P is a variable pattern <c>V</c>, then
+ Rep(P) = <c>{var,LINE,A}</c>,
where A is an atom with a printname consisting of the same characters as
- <c><![CDATA[V]]></c>.</item>
- <item>If P is a universal pattern <c><![CDATA[_]]></c>, then
- Rep(P) = <c><![CDATA[{var,LINE,'_'}]]></c>.</item>
- <item>If P is a tuple pattern <c><![CDATA[{P_1, ..., P_k}]]></c>, then
- Rep(P) = <c><![CDATA[{tuple,LINE,[Rep(P_1), ..., Rep(P_k)]}]]></c>.</item>
- <item>If P is a nil pattern <c><![CDATA[[]]]></c>, then
- Rep(P) = <c><![CDATA[{nil,LINE}]]></c>.</item>
- <item>If P is a cons pattern <c><![CDATA[[P_h | P_t]]]></c>, then
- Rep(P) = <c><![CDATA[{cons,LINE,Rep(P_h),Rep(P_t)}]]></c>.</item>
- <item>If E is a binary pattern <c><![CDATA[<<P_1:Size_1/TSL_1, ..., P_k:Size_k/TSL_k>>]]></c>, then
- Rep(E) = <c><![CDATA[{bin,LINE,[{bin_element,LINE,Rep(P_1),Rep(Size_1),Rep(TSL_1)}, ..., {bin_element,LINE,Rep(P_k),Rep(Size_k),Rep(TSL_k)}]}]]></c>.
+ <c>V</c>.</item>
+ <item>If P is a universal pattern <c>_</c>, then
+ Rep(P) = <c>{var,LINE,'_'}</c>.</item>
+ <item>If P is a tuple pattern <c>{P_1, ..., P_k}</c>, then
+ Rep(P) = <c>{tuple,LINE,[Rep(P_1), ..., Rep(P_k)]}</c>.</item>
+ <item>If P is a nil pattern <c>[]</c>, then
+ Rep(P) = <c>{nil,LINE}</c>.</item>
+ <item>If P is a cons pattern <c>[P_h | P_t]</c>, then
+ Rep(P) = <c>{cons,LINE,Rep(P_h),Rep(P_t)}</c>.</item>
+ <item>If E is a binary pattern <c>&lt;&lt;P_1:Size_1/TSL_1, ..., P_k:Size_k/TSL_k>></c>, then
+ Rep(E) = <c>{bin,LINE,[{bin_element,LINE,Rep(P_1),Rep(Size_1),Rep(TSL_1)}, ..., {bin_element,LINE,Rep(P_k),Rep(Size_k),Rep(TSL_k)}]}</c>.
For Rep(TSL), see below.
- An omitted <c><![CDATA[Size]]></c> is represented by <c><![CDATA[default]]></c>. An omitted <c><![CDATA[TSL]]></c>
- (type specifier list) is represented by <c><![CDATA[default]]></c>.</item>
- <item>If P is <c><![CDATA[P_1 Op P_2]]></c>, where <c><![CDATA[Op]]></c> is a binary operator (this
- is either an occurrence of <c><![CDATA[++]]></c> applied to a literal string or character
+ An omitted <c>Size</c> is represented by <c>default</c>. An omitted <c>TSL</c>
+ (type specifier list) is represented by <c>default</c>.</item>
+ <item>If P is <c>P_1 Op P_2</c>, where <c>Op</c> is a binary operator (this
+ is either an occurrence of <c>++</c> applied to a literal string or character
list, or an occurrence of an expression that can be evaluated to a number
at compile time),
- then Rep(P) = <c><![CDATA[{op,LINE,Op,Rep(P_1),Rep(P_2)}]]></c>.</item>
- <item>If P is <c><![CDATA[Op P_0]]></c>, where <c><![CDATA[Op]]></c> is a unary operator (this is an
+ then Rep(P) = <c>{op,LINE,Op,Rep(P_1),Rep(P_2)}</c>.</item>
+ <item>If P is <c>Op P_0</c>, where <c>Op</c> is a unary operator (this is an
occurrence of an expression that can be evaluated to a number at compile
- time), then Rep(P) = <c><![CDATA[{op,LINE,Op,Rep(P_0)}]]></c>.</item>
- <item>If P is a record pattern <c><![CDATA[#Name{Field_1=P_1, ..., Field_k=P_k}]]></c>,
+ time), then Rep(P) = <c>{op,LINE,Op,Rep(P_0)}</c>.</item>
+ <item>If P is a record pattern <c>#Name{Field_1=P_1, ..., Field_k=P_k}</c>,
then Rep(P) =
- <c><![CDATA[{record,LINE,Name, [{record_field,LINE,Rep(Field_1),Rep(P_1)}, ..., {record_field,LINE,Rep(Field_k),Rep(P_k)}]}]]></c>.</item>
- <item>If P is <c><![CDATA[#Name.Field]]></c>, then
- Rep(P) = <c><![CDATA[{record_index,LINE,Name,Rep(Field)}]]></c>.</item>
- <item>If P is <c><![CDATA[( P_0 )]]></c>, then
- Rep(P) = <c><![CDATA[Rep(P_0)]]></c>,
- i.e., patterns cannot be distinguished from their bodies.</item>
+ <c>{record,LINE,Name,[{record_field,LINE,Rep(Field_1),Rep(P_1)}, ..., {record_field,LINE,Rep(Field_k),Rep(P_k)}]}</c>.</item>
+ <item>If P is <c>#Name.Field</c>, then
+ Rep(P) = <c>{record_index,LINE,Name,Rep(Field)}</c>.</item>
+ <item>If P is <c>( P_0 )</c>, then
+ Rep(P) = <c>Rep(P_0)</c>,
+ that is, patterns cannot be distinguished from their bodies.</item>
</list>
<p>Note that every pattern has the same source form as some expression, and is
represented the same way as the corresponding expression.</p>
@@ -337,180 +221,167 @@
<section>
<title>Expressions</title>
- <p>A body B is a sequence of expressions <c><![CDATA[E_1, ..., E_k]]></c>, and
- Rep(B) = <c><![CDATA[[Rep(E_1), ..., Rep(E_k)]]]></c>.</p>
+ <p>A body B is a sequence of expressions <c>E_1, ..., E_k</c>, and
+ Rep(B) = <c>[Rep(E_1), ..., Rep(E_k)]</c>.</p>
<p>An expression E is one of the following alternatives:</p>
<list type="bulleted">
- <item>If P is an atomic literal <c><![CDATA[L]]></c>, then
- Rep(P) = Rep(L).</item>
- <item>If E is <c><![CDATA[P = E_0]]></c>, then
- Rep(E) = <c><![CDATA[{match,LINE,Rep(P),Rep(E_0)}]]></c>.</item>
- <item>If E is a variable <c><![CDATA[V]]></c>, then
- Rep(E) = <c><![CDATA[{var,LINE,A}]]></c>,
- where <c><![CDATA[A]]></c> is an atom with a printname consisting of the same
- characters as <c><![CDATA[V]]></c>.</item>
- <item>If E is a tuple skeleton <c><![CDATA[{E_1, ..., E_k}]]></c>, then
- Rep(E) = <c><![CDATA[{tuple,LINE,[Rep(E_1), ..., Rep(E_k)]}]]></c>.</item>
- <item>If E is <c><![CDATA[[]]]></c>, then
- Rep(E) = <c><![CDATA[{nil,LINE}]]></c>.</item>
- <item>If E is a cons skeleton <c><![CDATA[[E_h | E_t]]]></c>, then
- Rep(E) = <c><![CDATA[{cons,LINE,Rep(E_h),Rep(E_t)}]]></c>.</item>
- <item>If E is a binary constructor <c><![CDATA[<<V_1:Size_1/TSL_1, ..., V_k:Size_k/TSL_k>>]]></c>, then
- Rep(E) = <c><![CDATA[{bin,LINE,[{bin_element,LINE,Rep(V_1),Rep(Size_1),Rep(TSL_1)}, ..., {bin_element,LINE,Rep(V_k),Rep(Size_k),Rep(TSL_k)}]}]]></c>.
+ <item>If P is an atomic literal <c>L</c>, then Rep(P) = Rep(L).</item>
+ <item>If E is <c>P = E_0</c>, then
+ Rep(E) = <c>{match,LINE,Rep(P),Rep(E_0)}</c>.</item>
+ <item>If E is a variable <c>V</c>, then Rep(E) = <c>{var,LINE,A}</c>,
+ where <c>A</c> is an atom with a printname consisting of the same
+ characters as <c>V</c>.</item>
+ <item>If E is a tuple skeleton <c>{E_1, ..., E_k}</c>, then
+ Rep(E) = <c>{tuple,LINE,[Rep(E_1), ..., Rep(E_k)]}</c>.</item>
+ <item>If E is <c>[]</c>, then
+ Rep(E) = <c>{nil,LINE}</c>.</item>
+ <item>If E is a cons skeleton <c>[E_h | E_t]</c>, then
+ Rep(E) = <c>{cons,LINE,Rep(E_h),Rep(E_t)}</c>.</item>
+ <item>If E is a binary constructor <c>&lt;&lt;V_1:Size_1/TSL_1, ..., V_k:Size_k/TSL_k>></c>, then Rep(E) =
+ <c>{bin,LINE,[{bin_element,LINE,Rep(V_1),Rep(Size_1),Rep(TSL_1)}, ..., {bin_element,LINE,Rep(V_k),Rep(Size_k),Rep(TSL_k)}]}</c>.
For Rep(TSL), see below.
- An omitted <c><![CDATA[Size]]></c> is represented by <c><![CDATA[default]]></c>. An omitted <c><![CDATA[TSL]]></c>
- (type specifier list) is represented by <c><![CDATA[default]]></c>.</item>
- <item>If E is <c><![CDATA[E_1 Op E_2]]></c>, where <c><![CDATA[Op]]></c> is a binary operator,
- then Rep(E) = <c><![CDATA[{op,LINE,Op,Rep(E_1),Rep(E_2)}]]></c>.</item>
- <item>If E is <c><![CDATA[Op E_0]]></c>, where <c><![CDATA[Op]]></c> is a unary operator, then
- Rep(E) = <c><![CDATA[{op,LINE,Op,Rep(E_0)}]]></c>.</item>
- <item>If E is <c><![CDATA[#Name{Field_1=E_1, ..., Field_k=E_k}]]></c>, then
- Rep(E) =
- <c><![CDATA[{record,LINE,Name, [{record_field,LINE,Rep(Field_1),Rep(E_1)}, ..., {record_field,LINE,Rep(Field_k),Rep(E_k)}]}]]></c>.</item>
- <item>If E is <c><![CDATA[E_0#Name{Field_1=E_1, ..., Field_k=E_k}]]></c>, then
+ An omitted <c>Size</c> is represented by <c>default</c>. An omitted <c>TSL</c>
+ (type specifier list) is represented by <c>default</c>.</item>
+ <item>If E is <c>E_1 Op E_2</c>, where <c>Op</c> is a binary operator,
+ then Rep(E) = <c>{op,LINE,Op,Rep(E_1),Rep(E_2)}</c>.</item>
+ <item>If E is <c>Op E_0</c>, where <c>Op</c> is a unary operator, then
+ Rep(E) = <c>{op,LINE,Op,Rep(E_0)}</c>.</item>
+ <item>If E is <c>#Name{Field_1=E_1, ..., Field_k=E_k}</c>,
+ then Rep(E) =
+ <c>{record,LINE,Name,[{record_field,LINE,Rep(Field_1),Rep(E_1)}, ..., {record_field,LINE,Rep(Field_k),Rep(E_k)}]}</c>.</item>
+ <item>If E is <c>E_0#Name{Field_1=E_1, ..., Field_k=E_k}</c>, then
Rep(E) =
- <c><![CDATA[{record,LINE,Rep(E_0),Name, [{record_field,LINE,Rep(Field_1),Rep(E_1)}, ..., {record_field,LINE,Rep(Field_k),Rep(E_k)}]}]]></c>.</item>
- <item>If E is <c><![CDATA[#Name.Field]]></c>, then
- Rep(E) = <c><![CDATA[{record_index,LINE,Name,Rep(Field)}]]></c>.</item>
- <item>If E is <c><![CDATA[E_0#Name.Field]]></c>, then
- Rep(E) = <c><![CDATA[{record_field,LINE,Rep(E_0),Name,Rep(Field)}]]></c>.</item>
- <item>If E is <c><![CDATA[#{W_1, ..., W_k}]]></c> where each
- <c><![CDATA[W_i]]></c> is a map assoc or exact field, then Rep(E) =
- <c><![CDATA[{map,LINE,[Rep(W_1), ..., Rep(W_k)]}]]></c>. For Rep(W), see
+ <c>{record,LINE,Rep(E_0),Name,[{record_field,LINE,Rep(Field_1),Rep(E_1)}, ..., {record_field,LINE,Rep(Field_k),Rep(E_k)}]}</c>.</item>
+ <item>If E is <c>#Name.Field</c>, then
+ Rep(E) = <c>{record_index,LINE,Name,Rep(Field)}</c>.</item>
+ <item>If E is <c>E_0#Name.Field</c>, then
+ Rep(E) = <c>{record_field,LINE,Rep(E_0),Name,Rep(Field)}</c>.</item>
+ <item>If E is <c>#{W_1, ..., W_k}</c> where each
+ <c>W_i</c> is a map assoc or exact field, then Rep(E) =
+ <c>{map,LINE,[Rep(W_1), ..., Rep(W_k)]}</c>. For Rep(W), see
below.</item>
- <item>If E is <c><![CDATA[E_0#{W_1, ..., W_k}]]></c> where
- <c><![CDATA[W_i]]></c> is a map assoc or exact field, then Rep(E) =
- <c><![CDATA[{map,LINE,Rep(E_0),[Rep(W_1), ..., Rep(W_k)]}]]></c>. For
- Rep(W), see below.</item>
- <item>If E is <c><![CDATA[catch E_0]]></c>, then
- Rep(E) = <c><![CDATA[{'catch',LINE,Rep(E_0)}]]></c>.</item>
- <item>If E is <c><![CDATA[E_0(E_1, ..., E_k)]]></c>, then
- Rep(E) = <c><![CDATA[{call,LINE,Rep(E_0),[Rep(E_1), ..., Rep(E_k)]}]]></c>.</item>
- <item>If E is <c><![CDATA[E_m:E_0(E_1, ..., E_k)]]></c>, then
- Rep(E) =
- <c><![CDATA[{call,LINE,{remote,LINE,Rep(E_m),Rep(E_0)},[Rep(E_1), ..., Rep(E_k)]}]]></c>.</item>
- <item>If E is a list comprehension <c><![CDATA[[E_0 || W_1, ..., W_k]]]></c>,
- where each <c><![CDATA[W_i]]></c> is a generator or a filter, then
- Rep(E) = <c><![CDATA[{lc,LINE,Rep(E_0),[Rep(W_1), ..., Rep(W_k)]}]]></c>. For Rep(W), see
- below.</item>
- <item>If E is a binary comprehension <c><![CDATA[<<E_0 || W_1, ..., W_k>>]]></c>,
- where each <c><![CDATA[W_i]]></c> is a generator or a filter, then
- Rep(E) = <c><![CDATA[{bc,LINE,Rep(E_0),[Rep(W_1), ..., Rep(W_k)]}]]></c>. For Rep(W), see
+ <item>If E is <c>E_0#{W_1, ..., W_k}</c> where
+ <c>W_i</c> is a map assoc or exact field, then Rep(E) =
+ <c>{map,LINE,Rep(E_0),[Rep(W_1), ..., Rep(W_k)]}</c>.
+ For Rep(W), see below.</item>
+ <item>If E is <c>catch E_0</c>, then
+ Rep(E) = <c>{'catch',LINE,Rep(E_0)}</c>.</item>
+ <item>If E is <c>E_0(E_1, ..., E_k)</c>, then
+ Rep(E) = <c>{call,LINE,Rep(E_0),[Rep(E_1), ..., Rep(E_k)]}</c>.</item>
+ <item>If E is <c>E_m:E_0(E_1, ..., E_k)</c>, then Rep(E) =
+ <c>{call,LINE,{remote,LINE,Rep(E_m),Rep(E_0)},[Rep(E_1), ..., Rep(E_k)]}</c>.
+ </item>
+ <item>If E is a list comprehension <c>[E_0 || W_1, ..., W_k]</c>,
+ where each <c>W_i</c> is a generator or a filter, then Rep(E) =
+ <c>{lc,LINE,Rep(E_0),[Rep(W_1), ..., Rep(W_k)]}</c>. For Rep(W), see
below.</item>
- <item>If E is <c><![CDATA[begin B end]]></c>, where <c><![CDATA[B]]></c> is a body, then
- Rep(E) = <c><![CDATA[{block,LINE,Rep(B)}]]></c>.</item>
- <item>If E is <c><![CDATA[if Ic_1 ; ... ; Ic_k end]]></c>,
- where each <c><![CDATA[Ic_i]]></c> is an if clause then
- Rep(E) =
- <c><![CDATA[{'if',LINE,[Rep(Ic_1), ..., Rep(Ic_k)]}]]></c>.</item>
- <item>If E is <c><![CDATA[case E_0 of Cc_1 ; ... ; Cc_k end]]></c>,
- where <c><![CDATA[E_0]]></c> is an expression and each <c><![CDATA[Cc_i]]></c> is a
- case clause then
- Rep(E) =
- <c><![CDATA[{'case',LINE,Rep(E_0),[Rep(Cc_1), ..., Rep(Cc_k)]}]]></c>.</item>
- <item>If E is <c><![CDATA[try B catch Tc_1 ; ... ; Tc_k end]]></c>,
- where <c><![CDATA[B]]></c> is a body and each <c><![CDATA[Tc_i]]></c> is a catch clause then
- Rep(E) =
- <c><![CDATA[{'try',LINE,Rep(B),[],[Rep(Tc_1), ..., Rep(Tc_k)],[]}]]></c>.</item>
- <item>If E is <c><![CDATA[try B of Cc_1 ; ... ; Cc_k catch Tc_1 ; ... ; Tc_n end]]></c>,
- where <c><![CDATA[B]]></c> is a body,
- each <c><![CDATA[Cc_i]]></c> is a case clause and
- each <c><![CDATA[Tc_j]]></c> is a catch clause then
- Rep(E) =
- <c><![CDATA[{'try',LINE,Rep(B),[Rep(Cc_1), ..., Rep(Cc_k)],[Rep(Tc_1), ..., Rep(Tc_n)],[]}]]></c>.</item>
- <item>If E is <c><![CDATA[try B after A end]]></c>,
- where <c><![CDATA[B]]></c> and <c><![CDATA[A]]></c> are bodies then
- Rep(E) =
- <c><![CDATA[{'try',LINE,Rep(B),[],[],Rep(A)}]]></c>.</item>
- <item>If E is <c><![CDATA[try B of Cc_1 ; ... ; Cc_k after A end]]></c>,
- where <c><![CDATA[B]]></c> and <c><![CDATA[A]]></c> are a bodies and
- each <c><![CDATA[Cc_i]]></c> is a case clause then
- Rep(E) =
- <c><![CDATA[{'try',LINE,Rep(B),[Rep(Cc_1), ..., Rep(Cc_k)],[],Rep(A)}]]></c>.</item>
- <item>If E is <c><![CDATA[try B catch Tc_1 ; ... ; Tc_k after A end]]></c>,
- where <c><![CDATA[B]]></c> and <c><![CDATA[A]]></c> are bodies and
- each <c><![CDATA[Tc_i]]></c> is a catch clause then
- Rep(E) =
- <c><![CDATA[{'try',LINE,Rep(B),[],[Rep(Tc_1), ..., Rep(Tc_k)],Rep(A)}]]></c>.</item>
- <item>If E is <c><![CDATA[try B of Cc_1 ; ... ; Cc_k catch Tc_1 ; ... ; Tc_n after A end]]></c>,
- where <c><![CDATA[B]]></c> and <c><![CDATA[A]]></c> are a bodies,
- each <c><![CDATA[Cc_i]]></c> is a case clause and
- each <c><![CDATA[Tc_j]]></c> is a catch clause then
- Rep(E) =
- <c><![CDATA[{'try',LINE,Rep(B),[Rep(Cc_1), ..., Rep(Cc_k)],[Rep(Tc_1), ..., Rep(Tc_n)],Rep(A)}]]></c>.</item>
- <item>If E is <c><![CDATA[receive Cc_1 ; ... ; Cc_k end]]></c>,
- where each <c><![CDATA[Cc_i]]></c> is a case clause then
+ <item>If E is a binary comprehension
+ <c>&lt;&lt;E_0 || W_1, ..., W_k>></c>,
+ where each <c>W_i</c> is a generator or a filter, then
+ Rep(E) = <c>{bc,LINE,Rep(E_0),[Rep(W_1), ..., Rep(W_k)]}</c>.
+ For Rep(W), see below.</item>
+ <item>If E is <c>begin B end</c>, where <c>B</c> is a body, then
+ Rep(E) = <c>{block,LINE,Rep(B)}</c>.</item>
+ <item>If E is <c>if Ic_1 ; ... ; Ic_k end</c>,
+ where each <c>Ic_i</c> is an if clause then Rep(E) =
+ <c>{'if',LINE,[Rep(Ic_1), ..., Rep(Ic_k)]}</c>.</item>
+ <item>If E is <c>case E_0 of Cc_1 ; ... ; Cc_k end</c>,
+ where <c>E_0</c> is an expression and each <c>Cc_i</c> is a
+ case clause then Rep(E) =
+ <c>{'case',LINE,Rep(E_0),[Rep(Cc_1), ..., Rep(Cc_k)]}</c>.</item>
+ <item>If E is <c>try B catch Tc_1 ; ... ; Tc_k end</c>,
+ where <c>B</c> is a body and each <c>Tc_i</c> is a catch clause then
Rep(E) =
- <c><![CDATA[{'receive',LINE,[Rep(Cc_1), ..., Rep(Cc_k)]}]]></c>.</item>
- <item>If E is <c><![CDATA[receive Cc_1 ; ... ; Cc_k after E_0 -> B_t end]]></c>,
- where each <c><![CDATA[Cc_i]]></c> is a case clause,
- <c><![CDATA[E_0]]></c> is an expression and <c><![CDATA[B_t]]></c> is a body, then
+ <c>{'try',LINE,Rep(B),[],[Rep(Tc_1), ..., Rep(Tc_k)],[]}</c>.</item>
+ <item>If E is <c>try B of Cc_1 ; ... ; Cc_k catch Tc_1 ; ... ; Tc_n end</c>,
+ where <c>B</c> is a body,
+ each <c>Cc_i</c> is a case clause and
+ each <c>Tc_j</c> is a catch clause then Rep(E) =
+ <c>{'try',LINE,Rep(B),[Rep(Cc_1), ..., Rep(Cc_k)],[Rep(Tc_1), ..., Rep(Tc_n)],[]}</c>.</item>
+ <item>If E is <c>try B after A end</c>,
+ where <c>B</c> and <c>A</c> are bodies then Rep(E) =
+ <c>{'try',LINE,Rep(B),[],[],Rep(A)}</c>.</item>
+ <item>If E is <c>try B of Cc_1 ; ... ; Cc_k after A end</c>,
+ where <c>B</c> and <c>A</c> are a bodies and
+ each <c>Cc_i</c> is a case clause then Rep(E) =
+ <c>{'try',LINE,Rep(B),[Rep(Cc_1), ..., Rep(Cc_k)],[],Rep(A)}</c>.</item>
+ <item>If E is <c>try B catch Tc_1 ; ... ; Tc_k after A end</c>,
+ where <c>B</c> and <c>A</c> are bodies and
+ each <c>Tc_i</c> is a catch clause then Rep(E) =
+ <c>{'try',LINE,Rep(B),[],[Rep(Tc_1), ..., Rep(Tc_k)],Rep(A)}</c>.</item>
+ <item>If E is <c>try B of Cc_1 ; ... ; Cc_k catch Tc_1 ; ... ; Tc_n after A end</c>,
+ where <c>B</c> and <c>A</c> are a bodies,
+ each <c>Cc_i</c> is a case clause and
+ each <c>Tc_j</c> is a catch clause then
Rep(E) =
- <c><![CDATA[{'receive',LINE,[Rep(Cc_1), ..., Rep(Cc_k)],Rep(E_0),Rep(B_t)}]]></c>.</item>
- <item>If E is <c><![CDATA[fun Name / Arity]]></c>, then
- Rep(E) = <c><![CDATA[{'fun',LINE,{function,Name,Arity}}]]></c>.</item>
- <item>If E is <c><![CDATA[fun Module:Name/Arity]]></c>, then
- Rep(E) = <c><![CDATA[{'fun',LINE,{function,Rep(Module),Rep(Name),Rep(Arity)}}]]></c>.
- (Before the R15 release: Rep(E) = <c><![CDATA[{'fun',LINE,{function,Module,Name,Arity}}]]></c>.)</item>
- <item>If E is <c><![CDATA[fun Fc_1 ; ... ; Fc_k end]]></c>
- where each <c><![CDATA[Fc_i]]></c> is a function clause then Rep(E) =
- <c><![CDATA[{'fun',LINE,{clauses,[Rep(Fc_1), ..., Rep(Fc_k)]}}]]></c>.</item>
- <item>If E is <c><![CDATA[fun Name Fc_1 ; ... ; Name Fc_k end]]></c>
- where <c><![CDATA[Name]]></c> is a variable and each
- <c><![CDATA[Fc_i]]></c> is a function clause then Rep(E) =
- <c><![CDATA[{named_fun,LINE,Name,[Rep(Fc_1), ..., Rep(Fc_k)]}]]></c>.
+ <c>{'try',LINE,Rep(B),[Rep(Cc_1), ..., Rep(Cc_k)],[Rep(Tc_1), ..., Rep(Tc_n)],Rep(A)}</c>.</item>
+ <item>If E is <c>receive Cc_1 ; ... ; Cc_k end</c>,
+ where each <c>Cc_i</c> is a case clause then Rep(E) =
+ <c>{'receive',LINE,[Rep(Cc_1), ..., Rep(Cc_k)]}</c>.</item>
+ <item>If E is <c>receive Cc_1 ; ... ; Cc_k after E_0 -> B_t end</c>,
+ where each <c>Cc_i</c> is a case clause,
+ <c>E_0</c> is an expression and <c>B_t</c> is a body, then Rep(E) =
+ <c>{'receive',LINE,[Rep(Cc_1), ..., Rep(Cc_k)],Rep(E_0),Rep(B_t)}</c>.</item>
+ <item>If E is <c>fun Name / Arity</c>, then
+ Rep(E) = <c>{'fun',LINE,{function,Name,Arity}}</c>.</item>
+ <item>If E is <c>fun Module:Name/Arity</c>, then Rep(E) =
+ <c>{'fun',LINE,{function,Rep(Module),Rep(Name),Rep(Arity)}}</c>.
+ (Before the R15 release: Rep(E) =
+ <c>{'fun',LINE,{function,Module,Name,Arity}}</c>.)</item>
+ <item>If E is <c>fun Fc_1 ; ... ; Fc_k end</c>
+ where each <c>Fc_i</c> is a function clause then Rep(E) =
+ <c>{'fun',LINE,{clauses,[Rep(Fc_1), ..., Rep(Fc_k)]}}</c>.</item>
+ <item>If E is <c>fun Name Fc_1 ; ... ; Name Fc_k end</c>
+ where <c>Name</c> is a variable and each
+ <c>Fc_i</c> is a function clause then Rep(E) =
+ <c>{named_fun,LINE,Name,[Rep(Fc_1), ..., Rep(Fc_k)]}</c>.
</item>
- <item>If E is <c><![CDATA[query [E_0 || W_1, ..., W_k] end]]></c>,
- where each <c><![CDATA[W_i]]></c> is a generator or a filter, then
- Rep(E) = <c><![CDATA[{'query',LINE,{lc,LINE,Rep(E_0),[Rep(W_1), ..., Rep(W_k)]}}]]></c>.
- For Rep(W), see below.</item>
- <item>If E is <c><![CDATA[E_0.Field]]></c>, a Mnesia record access
- inside a query, then
- Rep(E) = <c><![CDATA[{record_field,LINE,Rep(E_0),Rep(Field)}]]></c>.</item>
- <item>If E is <c><![CDATA[( E_0 )]]></c>, then
- Rep(E) = <c><![CDATA[Rep(E_0)]]></c>,
- i.e., parenthesized expressions cannot be distinguished from their bodies.</item>
+ <item>If E is <c>( E_0 )</c>, then
+ Rep(E) = <c>Rep(E_0)</c>, that is, parenthesized
+ expressions cannot be distinguished from their bodies.</item>
</list>
<section>
- <title>Generators and filters</title>
- <p>When W is a generator or a filter (in the body of a list or binary comprehension), then:</p>
+ <title>Generators and Filters</title>
+ <p>When W is a generator or a filter (in the body of a list or
+ binary comprehension), then:</p>
<list type="bulleted">
- <item>If W is a generator <c><![CDATA[P <- E]]></c>, where <c><![CDATA[P]]></c> is a pattern and <c><![CDATA[E]]></c>
- is an expression, then
- Rep(W) = <c><![CDATA[{generate,LINE,Rep(P),Rep(E)}]]></c>.</item>
- <item>If W is a generator <c><![CDATA[P <= E]]></c>, where <c><![CDATA[P]]></c> is a pattern and <c><![CDATA[E]]></c>
- is an expression, then
- Rep(W) = <c><![CDATA[{b_generate,LINE,Rep(P),Rep(E)}]]></c>.</item>
- <item>If W is a filter <c><![CDATA[E]]></c>, which is an expression, then
- Rep(W) = <c><![CDATA[Rep(E)]]></c>.</item>
+ <item>If W is a generator <c>P &lt;- E</c>, where <c>P</c> is
+ a pattern and <c>E</c> is an expression, then
+ Rep(W) = <c>{generate,LINE,Rep(P),Rep(E)}</c>.</item>
+ <item>If W is a generator <c>P &lt;= E</c>, where <c>P</c> is
+ a pattern and <c>E</c> is an expression, then
+ Rep(W) = <c>{b_generate,LINE,Rep(P),Rep(E)}</c>.</item>
+ <item>If W is a filter <c>E</c>, which is an expression, then
+ Rep(W) = <c>Rep(E)</c>.</item>
</list>
</section>
<section>
- <title>Binary element type specifiers</title>
+ <title>Binary Element Type Specifiers</title>
<p>A type specifier list TSL for a binary element is a sequence of type
- specifiers <c><![CDATA[TS_1 - ... - TS_k]]></c>.
- Rep(TSL) = <c><![CDATA[[Rep(TS_1), ..., Rep(TS_k)]]]></c>.</p>
+ specifiers <c>TS_1 - ... - TS_k</c>.
+ Rep(TSL) = <c>[Rep(TS_1), ..., Rep(TS_k)]</c>.</p>
<p>When TS is a type specifier for a binary element, then:</p>
<list type="bulleted">
- <item>If TS is an atom <c><![CDATA[A]]></c>, Rep(TS) = <c><![CDATA[A]]></c>.</item>
- <item>If TS is a couple <c><![CDATA[A:Value]]></c> where <c><![CDATA[A]]></c> is an atom and <c><![CDATA[Value]]></c>
- is an integer, Rep(TS) = <c><![CDATA[{A, Value}]]></c>.</item>
+ <item>If TS is an atom <c>A</c>, then Rep(TS) = <c>A</c>.</item>
+ <item>If TS is a couple <c>A:Value</c> where <c>A</c> is an atom
+ and <c>Value</c> is an integer, then Rep(TS) =
+ <c>{A,Value}</c>.</item>
</list>
</section>
<section>
- <title>Map assoc and exact fields</title>
+ <title>Map Assoc and Exact Fields</title>
<p>When W is an assoc or exact field (in the body of a map), then:</p>
<list type="bulleted">
- <item>If W is an assoc field <c><![CDATA[K => V]]></c>, where
- <c><![CDATA[K]]></c> and <c><![CDATA[V]]></c> are both expressions,
- then Rep(W) = <c><![CDATA[{map_field_assoc,LINE,Rep(K),Rep(V)}]]></c>.
+ <item>If W is an assoc field <c>K => V</c>, where
+ <c>K</c> and <c>V</c> are both expressions,
+ then Rep(W) = <c>{map_field_assoc,LINE,Rep(K),Rep(V)}</c>.
</item>
- <item>If W is an exact field <c><![CDATA[K := V]]></c>, where
- <c><![CDATA[K]]></c> and <c><![CDATA[V]]></c> are both expressions,
- then Rep(W) = <c><![CDATA[{map_field_exact,LINE,Rep(K),Rep(V)}]]></c>.
+ <item>If W is an exact field <c>K := V</c>, where
+ <c>K</c> and <c>V</c> are both expressions,
+ then Rep(W) = <c>{map_field_exact,LINE,Rep(K),Rep(V)}</c>.
</item>
</list>
</section>
@@ -518,112 +389,220 @@
<section>
<title>Clauses</title>
- <p>There are function clauses, if clauses, case clauses
+ <p>There are function clauses, if clauses, case clauses
and catch clauses.</p>
- <p>A clause <c><![CDATA[C]]></c> is one of the following alternatives:</p>
+ <p>A clause <c>C</c> is one of the following alternatives:</p>
<list type="bulleted">
- <item>If C is a function clause <c><![CDATA[( Ps ) -> B]]></c>
- where <c><![CDATA[Ps]]></c> is a pattern sequence and <c><![CDATA[B]]></c> is a body, then
- Rep(C) = <c><![CDATA[{clause,LINE,Rep(Ps),[],Rep(B)}]]></c>.</item>
- <item>If C is a function clause <c><![CDATA[( Ps ) when Gs -> B]]></c>
- where <c><![CDATA[Ps]]></c> is a pattern sequence,
- <c><![CDATA[Gs]]></c> is a guard sequence and <c><![CDATA[B]]></c> is a body, then
- Rep(C) = <c><![CDATA[{clause,LINE,Rep(Ps),Rep(Gs),Rep(B)}]]></c>.</item>
- <item>If C is an if clause <c><![CDATA[Gs -> B]]></c>
- where <c><![CDATA[Gs]]></c> is a guard sequence and <c><![CDATA[B]]></c> is a body, then
- Rep(C) = <c><![CDATA[{clause,LINE,[],Rep(Gs),Rep(B)}]]></c>.</item>
- <item>If C is a case clause <c><![CDATA[P -> B]]></c>
- where <c><![CDATA[P]]></c> is a pattern and <c><![CDATA[B]]></c> is a body, then
- Rep(C) = <c><![CDATA[{clause,LINE,[Rep(P)],[],Rep(B)}]]></c>.</item>
- <item>If C is a case clause <c><![CDATA[P when Gs -> B]]></c>
- where <c><![CDATA[P]]></c> is a pattern,
- <c><![CDATA[Gs]]></c> is a guard sequence and <c><![CDATA[B]]></c> is a body, then
- Rep(C) = <c><![CDATA[{clause,LINE,[Rep(P)],Rep(Gs),Rep(B)}]]></c>.</item>
- <item>If C is a catch clause <c><![CDATA[P -> B]]></c>
- where <c><![CDATA[P]]></c> is a pattern and <c><![CDATA[B]]></c> is a body, then
- Rep(C) = <c><![CDATA[{clause,LINE,[Rep({throw,P,_})],[],Rep(B)}]]></c>.</item>
- <item>If C is a catch clause <c><![CDATA[X : P -> B]]></c>
- where <c><![CDATA[X]]></c> is an atomic literal or a variable pattern,
- <c><![CDATA[P]]></c> is a pattern and <c><![CDATA[B]]></c> is a body, then
- Rep(C) = <c><![CDATA[{clause,LINE,[Rep({X,P,_})],[],Rep(B)}]]></c>.</item>
- <item>If C is a catch clause <c><![CDATA[P when Gs -> B]]></c>
- where <c><![CDATA[P]]></c> is a pattern, <c><![CDATA[Gs]]></c> is a guard sequence
- and <c><![CDATA[B]]></c> is a body, then
- Rep(C) = <c><![CDATA[{clause,LINE,[Rep({throw,P,_})],Rep(Gs),Rep(B)}]]></c>.</item>
- <item>If C is a catch clause <c><![CDATA[X : P when Gs -> B]]></c>
- where <c><![CDATA[X]]></c> is an atomic literal or a variable pattern,
- <c><![CDATA[P]]></c> is a pattern, <c><![CDATA[Gs]]></c> is a guard sequence
- and <c><![CDATA[B]]></c> is a body, then
- Rep(C) = <c><![CDATA[{clause,LINE,[Rep({X,P,_})],Rep(Gs),Rep(B)}]]></c>.</item>
+ <item>If C is a function clause <c>( Ps ) -> B</c>
+ where <c>Ps</c> is a pattern sequence and <c>B</c> is a body, then
+ Rep(C) = <c>{clause,LINE,Rep(Ps),[],Rep(B)}</c>.</item>
+ <item>If C is a function clause <c>( Ps ) when Gs -> B</c>
+ where <c>Ps</c> is a pattern sequence,
+ <c>Gs</c> is a guard sequence and <c>B</c> is a body, then
+ Rep(C) = <c>{clause,LINE,Rep(Ps),Rep(Gs),Rep(B)}</c>.</item>
+ <item>If C is an if clause <c>Gs -> B</c>
+ where <c>Gs</c> is a guard sequence and <c>B</c> is a body, then
+ Rep(C) = <c>{clause,LINE,[],Rep(Gs),Rep(B)}</c>.</item>
+ <item>If C is a case clause <c>P -> B</c>
+ where <c>P</c> is a pattern and <c>B</c> is a body, then
+ Rep(C) = <c>{clause,LINE,[Rep(P)],[],Rep(B)}</c>.</item>
+ <item>If C is a case clause <c>P when Gs -> B</c>
+ where <c>P</c> is a pattern,
+ <c>Gs</c> is a guard sequence and <c>B</c> is a body, then
+ Rep(C) = <c>{clause,LINE,[Rep(P)],Rep(Gs),Rep(B)}</c>.</item>
+ <item>If C is a catch clause <c>P -> B</c>
+ where <c>P</c> is a pattern and <c>B</c> is a body, then
+ Rep(C) = <c>{clause,LINE,[Rep({throw,P,_})],[],Rep(B)}</c>.</item>
+ <item>If C is a catch clause <c>X : P -> B</c>
+ where <c>X</c> is an atomic literal or a variable pattern,
+ <c>P</c> is a pattern and <c>B</c> is a body, then
+ Rep(C) = <c>{clause,LINE,[Rep({X,P,_})],[],Rep(B)}</c>.</item>
+ <item>If C is a catch clause <c>P when Gs -> B</c>
+ where <c>P</c> is a pattern, <c>Gs</c> is a guard sequence
+ and <c>B</c> is a body, then
+ Rep(C) = <c>{clause,LINE,[Rep({throw,P,_})],Rep(Gs),Rep(B)}</c>.</item>
+ <item>If C is a catch clause <c>X : P when Gs -> B</c>
+ where <c>X</c> is an atomic literal or a variable pattern,
+ <c>P</c> is a pattern, <c>Gs</c> is a guard sequence
+ and <c>B</c> is a body, then
+ Rep(C) = <c>{clause,LINE,[Rep({X,P,_})],Rep(Gs),Rep(B)}</c>.</item>
</list>
</section>
<section>
<title>Guards</title>
- <p>A guard sequence Gs is a sequence of guards <c><![CDATA[G_1; ...; G_k]]></c>, and
- Rep(Gs) = <c><![CDATA[[Rep(G_1), ..., Rep(G_k)]]]></c>. If the guard sequence is
- empty, Rep(Gs) = <c><![CDATA[[]]]></c>.</p>
- <p>A guard G is a nonempty sequence of guard tests <c><![CDATA[Gt_1, ..., Gt_k]]></c>, and
- Rep(G) = <c><![CDATA[[Rep(Gt_1), ..., Rep(Gt_k)]]]></c>.</p>
- <p>A guard test <c><![CDATA[Gt]]></c> is one of the following alternatives:</p>
+ <p>A guard sequence Gs is a sequence of guards <c>G_1; ...; G_k</c>, and
+ Rep(Gs) = <c>[Rep(G_1), ..., Rep(G_k)]</c>. If the guard sequence is
+ empty, Rep(Gs) = <c>[]</c>.</p>
+ <p>A guard G is a nonempty sequence of guard tests
+ <c>Gt_1, ..., Gt_k</c>, and Rep(G) =
+ <c>[Rep(Gt_1), ..., Rep(Gt_k)]</c>.</p>
+ <p>A guard test <c>Gt</c> is one of the following alternatives:</p>
<list type="bulleted">
<item>If Gt is an atomic literal L, then Rep(Gt) = Rep(L).</item>
- <item>If Gt is a variable pattern <c><![CDATA[V]]></c>, then
- Rep(Gt) = <c><![CDATA[{var,LINE,A}]]></c>,
- where A is an atom with a printname consisting of the same characters as
- <c><![CDATA[V]]></c>.</item>
- <item>If Gt is a tuple skeleton <c><![CDATA[{Gt_1, ..., Gt_k}]]></c>, then
- Rep(Gt) = <c><![CDATA[{tuple,LINE,[Rep(Gt_1), ..., Rep(Gt_k)]}]]></c>.</item>
- <item>If Gt is <c><![CDATA[[]]]></c>, then
- Rep(Gt) = <c><![CDATA[{nil,LINE}]]></c>.</item>
- <item>If Gt is a cons skeleton <c><![CDATA[[Gt_h | Gt_t]]]></c>, then
- Rep(Gt) = <c><![CDATA[{cons,LINE,Rep(Gt_h),Rep(Gt_t)}]]></c>.</item>
- <item>If Gt is a binary constructor <c><![CDATA[<<Gt_1:Size_1/TSL_1, ..., Gt_k:Size_k/TSL_k>>]]></c>, then
- Rep(Gt) = <c><![CDATA[{bin,LINE,[{bin_element,LINE,Rep(Gt_1),Rep(Size_1),Rep(TSL_1)}, ..., {bin_element,LINE,Rep(Gt_k),Rep(Size_k),Rep(TSL_k)}]}]]></c>.
+ <item>If Gt is a variable pattern <c>V</c>, then
+ Rep(Gt) = <c>{var,LINE,A}</c>, where A is an atom with
+ a printname consisting of the same characters as <c>V</c>.</item>
+ <item>If Gt is a tuple skeleton <c>{Gt_1, ..., Gt_k}</c>, then
+ Rep(Gt) = <c>{tuple,LINE,[Rep(Gt_1), ..., Rep(Gt_k)]}</c>.</item>
+ <item>If Gt is <c>[]</c>, then Rep(Gt) = <c>{nil,LINE}</c>.</item>
+ <item>If Gt is a cons skeleton <c>[Gt_h | Gt_t]</c>, then
+ Rep(Gt) = <c>{cons,LINE,Rep(Gt_h),Rep(Gt_t)}</c>.</item>
+ <item>If Gt is a binary constructor
+ <c>&lt;&lt;Gt_1:Size_1/TSL_1, ..., Gt_k:Size_k/TSL_k>></c>, then
+ Rep(Gt) = <c>{bin,LINE,[{bin_element,LINE,Rep(Gt_1),Rep(Size_1),Rep(TSL_1)}, ..., {bin_element,LINE,Rep(Gt_k),Rep(Size_k),Rep(TSL_k)}]}</c>.
For Rep(TSL), see above.
- An omitted <c><![CDATA[Size]]></c> is represented by <c><![CDATA[default]]></c>. An omitted <c><![CDATA[TSL]]></c>
- (type specifier list) is represented by <c><![CDATA[default]]></c>.</item>
- <item>If Gt is <c><![CDATA[Gt_1 Op Gt_2]]></c>, where <c><![CDATA[Op]]></c>
- is a binary operator, then Rep(Gt) = <c><![CDATA[{op,LINE,Op,Rep(Gt_1),Rep(Gt_2)}]]></c>.</item>
- <item>If Gt is <c><![CDATA[Op Gt_0]]></c>, where <c><![CDATA[Op]]></c> is a unary operator, then
- Rep(Gt) = <c><![CDATA[{op,LINE,Op,Rep(Gt_0)}]]></c>.</item>
- <item>If Gt is <c><![CDATA[#Name{Field_1=Gt_1, ..., Field_k=Gt_k}]]></c>, then
+ An omitted <c>Size</c> is represented by <c>default</c>.
+ An omitted <c>TSL</c> (type specifier list) is represented
+ by <c>default</c>.</item>
+ <item>If Gt is <c>Gt_1 Op Gt_2</c>, where <c>Op</c>
+ is a binary operator, then Rep(Gt) =
+ <c>{op,LINE,Op,Rep(Gt_1),Rep(Gt_2)}</c>.</item>
+ <item>If Gt is <c>Op Gt_0</c>, where <c>Op</c> is a unary operator, then
+ Rep(Gt) = <c>{op,LINE,Op,Rep(Gt_0)}</c>.</item>
+ <item>If Gt is <c>#Name{Field_1=Gt_1, ..., Field_k=Gt_k}</c>, then
Rep(E) =
- <c><![CDATA[{record,LINE,Name, [{record_field,LINE,Rep(Field_1),Rep(Gt_1)}, ..., {record_field,LINE,Rep(Field_k),Rep(Gt_k)}]}]]></c>.</item>
- <item>If Gt is <c><![CDATA[#Name.Field]]></c>, then
- Rep(Gt) = <c><![CDATA[{record_index,LINE,Name,Rep(Field)}]]></c>.</item>
- <item>If Gt is <c><![CDATA[Gt_0#Name.Field]]></c>, then
- Rep(Gt) = <c><![CDATA[{record_field,LINE,Rep(Gt_0),Name,Rep(Field)}]]></c>.</item>
- <item>If Gt is <c><![CDATA[A(Gt_1, ..., Gt_k)]]></c>, where <c><![CDATA[A]]></c> is an atom, then
- Rep(Gt) = <c><![CDATA[{call,LINE,Rep(A),[Rep(Gt_1), ..., Rep(Gt_k)]}]]></c>.</item>
- <item>If Gt is <c><![CDATA[A_m:A(Gt_1, ..., Gt_k)]]></c>, where <c><![CDATA[A_m]]></c> is
- the atom <c><![CDATA[erlang]]></c> and <c><![CDATA[A]]></c> is an atom or an operator, then
- Rep(Gt) = <c><![CDATA[{call,LINE,{remote,LINE,Rep(A_m),Rep(A)},[Rep(Gt_1), ..., Rep(Gt_k)]}]]></c>.</item>
- <item>If Gt is <c><![CDATA[{A_m,A}(Gt_1, ..., Gt_k)]]></c>, where <c><![CDATA[A_m]]></c> is
- the atom <c><![CDATA[erlang]]></c> and <c><![CDATA[A]]></c> is an atom or an operator, then
- Rep(Gt) = <c><![CDATA[{call,LINE,Rep({A_m,A}),[Rep(Gt_1), ..., Rep(Gt_k)]}]]></c>.</item>
- <item>If Gt is <c><![CDATA[( Gt_0 )]]></c>, then
- Rep(Gt) = <c><![CDATA[Rep(Gt_0)]]></c>,
- i.e., parenthesized guard tests cannot be distinguished from their bodies.</item>
+ <c>{record,LINE,Name,[{record_field,LINE,Rep(Field_1),Rep(Gt_1)}, ..., {record_field,LINE,Rep(Field_k),Rep(Gt_k)}]}</c>.</item>
+ <item>If Gt is <c>#Name.Field</c>, then
+ Rep(Gt) = <c>{record_index,LINE,Name,Rep(Field)}</c>.</item>
+ <item>If Gt is <c>Gt_0#Name.Field</c>, then
+ Rep(Gt) = <c>{record_field,LINE,Rep(Gt_0),Name,Rep(Field)}</c>.</item>
+ <item>If Gt is <c>A(Gt_1, ..., Gt_k)</c>, where <c>A</c> is an atom, then
+ Rep(Gt) = <c>{call,LINE,Rep(A),[Rep(Gt_1), ..., Rep(Gt_k)]}</c>.</item>
+ <item>If Gt is <c>A_m:A(Gt_1, ..., Gt_k)</c>, where <c>A_m</c> is
+ the atom <c>erlang</c> and <c>A</c> is an atom or an operator, then
+ Rep(Gt) = <c>{call,LINE,{remote,LINE,Rep(A_m),Rep(A)},[Rep(Gt_1), ..., Rep(Gt_k)]}</c>.</item>
+ <item>If Gt is <c>{A_m,A}(Gt_1, ..., Gt_k)</c>, where <c>A_m</c> is
+ the atom <c>erlang</c> and <c>A</c> is an atom or an operator, then
+ Rep(Gt) = <c>{call,LINE,Rep({A_m,A}),[Rep(Gt_1), ..., Rep(Gt_k)]}</c>.
+ </item>
+ <item>If Gt is <c>( Gt_0 )</c>, then
+ Rep(Gt) = <c>Rep(Gt_0)</c>, that is, parenthesized
+ guard tests cannot be distinguished from their bodies.</item>
</list>
<p>Note that every guard test has the same source form as some expression,
and is represented the same way as the corresponding expression.</p>
</section>
<section>
- <title>The abstract format after preprocessing</title>
- <p>The compilation option <c><![CDATA[debug_info]]></c> can be given to the
- compiler to have the abstract code stored in
- the <c><![CDATA[abstract_code]]></c> chunk in the BEAM file
+ <title>Types</title>
+ <list type="bulleted">
+ <item>If T is an annotated type <c>Anno :: Type</c>,
+ where <c>Anno</c> is a variable and
+ <c>Type</c> is a type, then Rep(T) =
+ <c>{ann_type,LINE,[Rep(Anno),Rep(Type)]}</c>.</item>
+ <item>If T is an atom or integer literal L, then Rep(T) = Rep(L).
+ </item>
+ <item>If T is <c>L Op R</c>,
+ where <c>Op</c> is a binary operator and <c>L</c> and <c>R</c>
+ are types (this is an occurrence of an expression that can be
+ evaluated to an integer at compile time), then
+ Rep(T) = <c>{op,LINE,Op,Rep(L),Rep(R)}</c>.</item>
+ <item>If T is <c>Op A</c>, where <c>Op</c> is a
+ unary operator and <c>A</c> is a type (this is an occurrence of
+ an expression that can be evaluated to an integer at compile time),
+ then Rep(T) = <c>{op,LINE,Op,Rep(A)}</c>.</item>
+ <item>If T is a bitstring type <c>&lt;&lt;_:M,_:_*N>></c>,
+ where <c>M</c> and <c>N</c> are singleton integer types, then Rep(T) =
+ <c>{type,LINE,binary,[Rep(M),Rep(N)]}</c>.</item>
+ <item>If T is the empty list type <c>[]</c>, then Rep(T) =
+ <c>{type,Line,nil,[]}</c>.</item>
+ <item>If T is a fun type <c>fun()</c>, then Rep(T) =
+ <c>{type,LINE,'fun',[]}</c>.</item>
+ <item>If T is a fun type <c>fun((...) -> B)</c>,
+ where <c>B</c> is a type, then
+ Rep(T) = <c>{type,LINE,'fun',[{type,LINE,any},Rep(B)]}</c>.
+ </item>
+ <item>If T is a fun type <c>fun(Ft)</c>, where
+ <c>Ft</c> is a function type,
+ then Rep(T) = <c>Rep(Ft)</c>.</item>
+ <item>If T is an integer range type <c>L .. H</c>,
+ where <c>L</c> and <c>H</c> are singleton integer types, then
+ Rep(T) = <c>{type,LINE,range,[Rep(L),Rep(H)]}</c>.</item>
+ <item>If T is a map type <c>map()</c>, then Rep(T) =
+ <c>{type,LINE,map,any}</c>.</item>
+ <item>If T is a map type <c>#{P_1, ..., P_k}</c>, where each
+ <c>P_i</c> is a map pair type, then Rep(T) =
+ <c>{type,LINE,map,[Rep(P_1), ..., Rep(P_k)]}</c>.</item>
+ <item>If T is a map pair type <c>K => V</c>, where
+ <c>K</c> and <c>V</c> are types, then Rep(T) =
+ <c>{type,LINE,map_field_assoc,[Rep(K),Rep(V)]}</c>.</item>
+ <item>If T is a predefined (or built-in) type <c>N(A_1, ..., A_k)</c>,
+ where each <c>A_i</c> is a type, then Rep(T) =
+ <c>{type,LINE,N,[Rep(A_1), ..., Rep(A_k)]}</c>.</item>
+ <item>If T is a record type <c>#Name{F_1, ..., F_k}</c>,
+ where each <c>F_i</c> is a record field type, then Rep(T) =
+ <c>{type,LINE,record,[Rep(Name),Rep(F_1), ..., Rep(F_k)]}</c>.
+ </item>
+ <item>If T is a record field type <c>Name :: Type</c>,
+ where <c>Type</c> is a type, then Rep(T) =
+ <c>{type,LINE,field_type,[Rep(Name),Rep(Type)]}</c>.</item>
+ <item>If T is a remote type <c>M:N(A_1, ..., A_k)</c>, where
+ each <c>A_i</c> is a type, then Rep(T) =
+ <c>{remote_type,LINE,[Rep(M),Rep(N),[Rep(A_1), ..., Rep(A_k)]]}</c>.
+ </item>
+ <item>If T is a tuple type <c>tuple()</c>, then Rep(T) =
+ <c>{type,LINE,tuple,any}</c>.</item>
+ <item>If T is a tuple type <c>{A_1, ..., A_k}</c>, where
+ each <c>A_i</c> is a type, then Rep(T) =
+ <c>{type,LINE,tuple,[Rep(A_1), ..., Rep(A_k)]}</c>.</item>
+ <item>If T is a type union <c>T_1 | ... | T_k</c>,
+ where each <c>T_i</c> is a type, then Rep(T) =
+ <c>{type,LINE,union,[Rep(T_1), ..., Rep(T_k)]}</c>.</item>
+ <item>If T is a type variable <c>V</c>, then Rep(T) =
+ <c>{var,LINE,A}</c>, where <c>A</c> is an atom with a printname
+ consisting of the same characters as <c>V</c>. A type variable
+ is any variable except underscore (<c>_</c>).</item>
+ <item>If T is a user-defined type <c>N(A_1, ..., A_k)</c>,
+ where each <c>A_i</c> is a type, then Rep(T) =
+ <c>{user_type,LINE,N,[Rep(A_1), ..., Rep(A_k)]}</c>.</item>
+ <item>If T is <c>( T_0 )</c>, then Rep(T) = <c>Rep(T_0)</c>,
+ that is, parenthesized types cannot be distinguished from their
+ bodies.</item>
+ </list>
+
+ <section>
+ <title>Function Types</title>
+ <list type="bulleted">
+ <item>If Ft is a constrained function type <c>Ft_1 when Fc</c>,
+ where <c>Ft_1</c> is a function type and
+ <c>Fc</c> is a function constraint, then Rep(T) =
+ <c>{type,LINE,bounded_fun,[Rep(Ft_1),Rep(Fc)]}</c>.</item>
+ <item>If Ft is a function type <c>(A_1, ..., A_n) -> B</c>,
+ where each <c>A_i</c> and <c>B</c> are types, then
+ Rep(Ft) = <c>{type,LINE,'fun',[{type,LINE,product,[Rep(A_1),
+ ..., Rep(A_n)]},Rep(B)]}</c>.</item>
+ </list>
+ </section>
+
+ <section>
+ <title>Function Constraints</title>
+ <p>A function constraint Fc is a nonempty sequence of constraints
+ <c>C_1, ..., C_k</c>, and
+ Rep(Fc) = <c>[Rep(C_1), ..., Rep(C_k)]</c>.</p>
+ <list type="bulleted">
+ <item>If C is a constraint <c>is_subtype(V, T)</c> or <c>V :: T</c>,
+ where <c>V</c> is a type variable and <c>T</c> is a type, then
+ Rep(C) = <c>{type,LINE,constraint,[{atom,LINE,is_subtype},[Rep(V),Rep(T)]]}</c>.
+ </item>
+ </list>
+ </section>
+ </section>
+
+ <section>
+ <title>The Abstract Format After Preprocessing</title>
+ <p>The compilation option <c>debug_info</c> can be given to the
+ compiler to have the abstract code stored in
+ the <c>abstract_code</c> chunk in the BEAM file
(for debugging purposes).</p>
- <p>In OTP R9C and later, the <c><![CDATA[abstract_code]]></c> chunk will
+ <p>In OTP R9C and later, the <c>abstract_code</c> chunk will
contain</p>
- <p><c><![CDATA[{raw_abstract_v1,AbstractCode}]]></c></p>
- <p>where <c><![CDATA[AbstractCode]]></c> is the abstract code as described
+ <p><c>{raw_abstract_v1,AbstractCode}</c></p>
+ <p>where <c>AbstractCode</c> is the abstract code as described
in this document.</p>
<p>In releases of OTP prior to R9C, the abstract code after some more
processing was stored in the BEAM file. The first element of the
- tuple would be either <c><![CDATA[abstract_v1]]></c> (R7B) or <c><![CDATA[abstract_v2]]></c>
+ tuple would be either <c>abstract_v1</c> (R7B) or <c>abstract_v2</c>
(R8B).</p>
</section>
</chapter>
diff --git a/erts/doc/src/erl.xml b/erts/doc/src/erl.xml
index 63ab2532ab..b6fa4c254c 100644
--- a/erts/doc/src/erl.xml
+++ b/erts/doc/src/erl.xml
@@ -371,7 +371,7 @@
path, similar to <c><![CDATA[code:add_pathsa/1]]></c>. See
<seealso marker="kernel:code">code(3)</seealso>.
As an alternative to <c>-pa</c>, if several directories are
- to be prepended to the code and the directories have a
+ to be prepended to the code path and the directories have a
common parent directory, that parent directory could be
specified in the <c>ERL_LIBS</c> environment variable.
See <seealso marker="kernel:code">code(3)</seealso>.</p>
@@ -1184,7 +1184,7 @@
disables this feature, which also is the default.
</p>
<p>This feature has been introduced as a temporary workaround
- for lengthy executing native code, and native code that do not
+ for long-executing native code, and native code that does not
bump reductions properly in OTP. When these bugs have be fixed
the <c>+sfwi</c> flag will be removed.
</p>
@@ -1210,7 +1210,7 @@
balance scheduler utilization between schedulers. That is,
strive for equal scheduler utilization on all schedulers.
<br/>&nbsp;&nbsp;&nbsp;<c>+sub true</c> is only supported on
- systems where the runtime system detects and use a monotonically
+ systems where the runtime system detects and uses a monotonically
increasing high resolution clock. On other systems, the runtime
system will fail to start.
<br/>&nbsp;&nbsp;&nbsp;<c>+sub true</c> implies
@@ -1334,6 +1334,21 @@
<seealso marker="kernel:error_logger#warning_map/0">error_logger(3)</seealso>
for further information.</p>
</item>
+ <tag><c><![CDATA[+xFlag Value]]></c></tag>
+ <item>
+ <p>Default process flag settings.</p>
+ <taglist>
+ <tag><marker id="+xmqd"><c>+xmqd off_heap|on_heap|mixed</c></marker></tag>
+ <item><p>
+ Sets the default value for the process flag
+ <c>message_queue_data</c>. If <c>+xmqd</c> is not
+ passed, <c>mixed</c> will be the default. For more information,
+ see the documentation of
+ <seealso marker="erlang#process_flag_message_queue_data"><c>process_flag(message_queue_data,
+ MQD)</c></seealso>.
+ </p></item>
+ </taglist>
+ </item>
<tag><c><![CDATA[+zFlag Value]]></c></tag>
<item>
<p>Miscellaneous flags.</p>
diff --git a/erts/doc/src/erl_driver.xml b/erts/doc/src/erl_driver.xml
index ef6d69cbeb..cade732c56 100644
--- a/erts/doc/src/erl_driver.xml
+++ b/erts/doc/src/erl_driver.xml
@@ -2856,7 +2856,7 @@ ERL_DRV_MAP int sz
</func>
<func>
- <name><ret>int</ret><nametext>erl_drv_putenv(char *key, char *value)</nametext></name>
+ <name><ret>int</ret><nametext>erl_drv_putenv(const char *key, char *value)</nametext></name>
<fsummary>Set the value of an environment variable</fsummary>
<desc>
<marker id="erl_drv_putenv"></marker>
@@ -2885,7 +2885,7 @@ ERL_DRV_MAP int sz
</desc>
</func>
<func>
- <name><ret>int</ret><nametext>erl_drv_getenv(char *key, char *value, size_t *value_size)</nametext></name>
+ <name><ret>int</ret><nametext>erl_drv_getenv(const char *key, char *value, size_t *value_size)</nametext></name>
<fsummary>Get the value of an environment variable</fsummary>
<desc>
<marker id="erl_drv_getenv"></marker>
diff --git a/erts/doc/src/erl_nif.xml b/erts/doc/src/erl_nif.xml
index dae14b8d08..2d8706169f 100644
--- a/erts/doc/src/erl_nif.xml
+++ b/erts/doc/src/erl_nif.xml
@@ -791,6 +791,10 @@ typedef enum {
and return true, or return false if <c>term</c> is not an unsigned integer or is
outside the bounds of type <c>unsigned long</c>.</p></desc>
</func>
+ <func><name><ret>int</ret><nametext>enif_getenv(const char* key, char* value, size_t *value_size)</nametext></name>
+ <fsummary>Get the value of an environment variable</fsummary>
+ <desc><p>Same as <seealso marker="erl_driver#erl_drv_getenv">erl_drv_getenv</seealso>.</p></desc>
+ </func>
<func><name><ret>int</ret><nametext>enif_has_pending_exception(ErlNifEnv* env, ERL_NIF_TERM* reason)</nametext></name>
<fsummary>Check if an exception has been raised</fsummary>
<desc><p>Return true if a pending exception is associated
diff --git a/erts/doc/src/erl_prim_loader.xml b/erts/doc/src/erl_prim_loader.xml
index d05f0d9aea..db4f132609 100644
--- a/erts/doc/src/erl_prim_loader.xml
+++ b/erts/doc/src/erl_prim_loader.xml
@@ -36,17 +36,11 @@
the system. The start script is also fetched with this low level
loader.</p>
<p><c>erl_prim_loader</c> knows about the environment and how to
- fetch modules. The loader could, for example, fetch files using
- the file system (with absolute file names as input), or a
- database (where the binary format of a module is stored).</p>
+ fetch modules.</p>
<p>The <c>-loader Loader</c> command line flag can be used to
choose the method used by the <c>erl_prim_loader</c>. Two
<c>Loader</c> methods are supported by the Erlang runtime system:
- <c>efile</c> and <c>inet</c>. If another loader is required, then
- it has to be implemented by the user. The <c>Loader</c> provided
- by the user must fulfill the protocol defined below, and it is
- started with the <c>erl_prim_loader</c> by evaluating
- <c>open_port({spawn,Loader},[binary])</c>.</p>
+ <c>efile</c> and <c>inet</c>.</p>
<warning><p>The support for loading of code from archive files is
experimental. The sole purpose of releasing it before it is ready
@@ -83,9 +77,6 @@
started on each of hosts given in <c><anno>Hosts</anno></c> in order to
answer the requests. See <seealso
marker="kernel:erl_boot_server">erl_boot_server(3)</seealso>.</p>
- <p>If <c>-loader</c> is something else, the given port program
- is started. The port program is supposed to follow
- the protocol specified below.</p>
</desc>
</func>
<func>
@@ -175,22 +166,6 @@
</funcs>
<section>
- <title>Protocol</title>
- <p>The following protocol must be followed if a user provided
- loader port program is used. The <c>Loader</c> port program is
- started with the command
- <c>open_port({spawn,Loader},[binary])</c>. The protocol is as
- follows:</p>
- <pre>
-Function Send Receive
--------------------------------------------------------------
-get_file [102 | FileName] [121 | BinaryFile] (on success)
- [122] (failure)
-
-stop eof terminate</pre>
- </section>
-
- <section>
<title>Command Line Flags</title>
<p>The <c>erl_prim_loader</c> module interprets the following
command line flags:</p>
@@ -199,10 +174,8 @@ stop eof terminate</pre>
<item>
<p>Specifies the name of the loader used by
<c>erl_prim_loader</c>. <c>Loader</c> can be <c>efile</c>
- (use the local file system), or <c>inet</c> (load using
- the <c>boot_server</c> on another Erlang node). If
- <c>Loader</c> is user defined, the defined <c>Loader</c> port
- program is started.</p>
+ (use the local file system) or <c>inet</c> (load using
+ the <c>boot_server</c> on another Erlang node).</p>
<p>If the <c>-loader</c> flag is omitted, it defaults to
<c>efile</c>.</p>
</item>
diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml
index 3927339b2b..6ed03f3dfc 100644
--- a/erts/doc/src/erlang.xml
+++ b/erts/doc/src/erlang.xml
@@ -59,6 +59,12 @@
</datatype>
<datatype>
+ <name name="message_queue_data"></name>
+ <desc><p>See <seealso marker="#process_flag_message_queue_data"><c>erlang:process_flag(message_queue_data, MQD)</c></seealso>.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
<name name="timestamp"></name>
<desc><p>See <seealso marker="#timestamp/0">erlang:timestamp/0</seealso>.</p>
</desc>
@@ -1001,15 +1007,15 @@
can be used instead of
<c>demonitor(<anno>MonitorRef</anno>)</c> if this cleanup is wanted.</p>
<note>
- <p>Before OTP R11B (<c>ERTS</c> 5.5), <c>demonitor/1</c>
- behaved asynchronous, that is, the monitor was active
- until the "demonitor signal" reached the monitored entity.
- This had an undesirable effect, as you could never know when
- you were guaranteed <em>not</em> to receive a <c>DOWN</c>
- message because of the monitor.</p>
- <p>The current behavior can be viewed as two combined operations:
- asynchronously send a "demonitor signal" to the monitored
- entity and ignore any future results of the monitor.</p>
+ <p>Prior to OTP release R11B (ERTS version 5.5) <c>demonitor/1</c>
+ behaved completely asynchronously, i.e., the monitor was active
+ until the "demonitor signal" reached the monitored entity. This
+ had one undesirable effect. You could never know when
+ you were guaranteed <em>not</em> to receive a <c>DOWN</c> message
+ due to the monitor.</p>
+ <p>Current behavior can be viewed as two combined operations:
+ asynchronously send a "demonitor signal" to the monitored entity
+ and ignore any future results of the monitor. </p>
</note>
<p>Failure: It is an error if <c><anno>MonitorRef</anno></c> refers to a
monitoring started by another process. Not all such cases are
@@ -4280,9 +4286,59 @@ os_prompt% </pre>
<p>Returns the old value of the flag.</p>
</desc>
</func>
-
+ <marker id="process_flag_message_queue_data"/>
<func>
<name name="process_flag" arity="2" clause_i="5"/>
+ <fsummary>Set process flag <c>message_queue_data</c> for the calling process</fsummary>
+ <type name="message_queue_data"/>
+ <desc>
+ <p>This flag determines how messages in the message queue
+ are stored. When the flag is:</p>
+ <taglist>
+ <tag><c>off_heap</c></tag>
+ <item><p>
+ <em>All</em> messages in the message queue will be stored
+ outside of the process heap. This implies that <em>no</em>
+ messages in the message queue will be part of a garbage
+ collection of the process.
+ </p></item>
+ <tag><c>on_heap</c></tag>
+ <item><p>
+ All messages in the message queue will eventually be
+ placed on heap. They may however temporarily be stored
+ off heap. This is how messages always have been stored
+ up until ERTS version 8.0.
+ </p></item>
+ <tag><c>mixed</c></tag>
+ <item><p>
+ Messages may be placed either on the heap or outside
+ of the heap.
+ </p></item>
+ </taglist>
+ <p>
+ The default <c>message_queue_data</c> process flag is determined
+ by the <seealso marker="erl#+xmqd"><c>+xmqd</c></seealso>
+ <c>erl</c> command line argument.
+ </p>
+ <p>
+ If the process potentially may get a hugh amount of messages,
+ you are recommended to set the flag to <c>off_heap</c>. This
+ since a garbage collection with lots of messages placed on
+ the heap may become extremly expensive and the process may
+ consume large amounts of memory. Performance of the
+ actual message passing is however generally better when not
+ using the <c>off_heap</c> flag.
+ </p>
+ <p>
+ When changing this flag messages will be moved. This work
+ has been initiated but not completed when this function
+ call returns.
+ </p>
+ <p>Returns the old value of the flag.</p>
+ </desc>
+ </func>
+ <func>
+ <name name="process_flag" arity="2" clause_i="6"/>
<fsummary>Sets process flag <c>priority</c> for the calling process.</fsummary>
<type name="priority_level"/>
<desc>
@@ -4356,7 +4412,7 @@ os_prompt% </pre>
</func>
<func>
- <name name="process_flag" arity="2" clause_i="6"/>
+ <name name="process_flag" arity="2" clause_i="7"/>
<fsummary>Sets process flag <c>save_calls</c> for the calling process.</fsummary>
<desc>
<p><c><anno>N</anno></c> must be an integer in the interval 0..10000.
@@ -4387,7 +4443,7 @@ os_prompt% </pre>
</func>
<func>
- <name name="process_flag" arity="2" clause_i="7"/>
+ <name name="process_flag" arity="2" clause_i="8"/>
<fsummary>Sets process flag <c>sensitive</c> for the calling process.</fsummary>
<desc>
<p>Sets or clears flag <c>sensitive</c> for the current process.
@@ -4441,6 +4497,7 @@ os_prompt% </pre>
<type name="process_info_result_item"/>
<type name="priority_level"/>
<type name="stack_item"/>
+ <type name="message_queue_data" />
<desc>
<p>Returns a list containing <c><anno>InfoTuple</anno></c>s with
miscellaneous information about the process identified by
@@ -4493,6 +4550,7 @@ os_prompt% </pre>
<type name="process_info_result_item"/>
<type name="stack_item"/>
<type name="priority_level"/>
+ <type name="message_queue_data" />
<desc>
<p>Returns information about the process identified by
<c><anno>Pid</anno></c>, as specified by
@@ -4661,6 +4719,15 @@ os_prompt% </pre>
monitor by name, the list item is
<c>{process, {<anno>RegName</anno>, <anno>Node</anno>}}</c>.</p>
</item>
+ <tag><c>{message_queue_data, <anno>MQD</anno>}</c></tag>
+ <item>
+ <p>Returns the current state of the <c>message_queue_data</c>
+ process flag. <c><anno>MQD</anno></c> is either <c>off_heap</c>,
+ <c>on_heap</c>, or <c>mixed</c>. For more information, see the
+ documentation of
+ <seealso marker="#process_flag_message_queue_data"><c>process_flag(message_queue_data,
+ MQD)</c></seealso>.</p>
+ </item>
<tag><c>{priority, <anno>Level</anno>}</c></tag>
<item>
<p><c><anno>Level</anno></c> is the current priority level for
@@ -5429,6 +5496,8 @@ true</pre>
<name name="spawn_opt" arity="2"/>
<fsummary>Creates a new process with a fun as entry point.</fsummary>
<type name="priority_level"/>
+ <type name="message_queue_data" />
+ <type name="spawn_opt_option" />
<desc>
<p>Returns the process identifier (pid) of a new process
started by the application of <c><anno>Fun</anno></c>
@@ -5444,6 +5513,8 @@ true</pre>
<name name="spawn_opt" arity="3"/>
<fsummary>Creates a new process with a fun as entry point on a given node.</fsummary>
<type name="priority_level"/>
+ <type name="message_queue_data" />
+ <type name="spawn_opt_option" />
<desc>
<p>Returns the process identifier (pid) of a new process started
by the application of <c><anno>Fun</anno></c> to the
@@ -5458,6 +5529,8 @@ true</pre>
<name name="spawn_opt" arity="4"/>
<fsummary>Creates a new process with a function as entry point.</fsummary>
<type name="priority_level"/>
+ <type name="message_queue_data" />
+ <type name="spawn_opt_option" />
<desc>
<p>Works as
<seealso marker="#spawn/3">spawn/3</seealso>, except that an
@@ -5559,6 +5632,18 @@ true</pre>
fine-tuning an application and to measure the execution
time with various <c><anno>VSize</anno></c> values.</p>
</item>
+ <tag><c>{message_queue_data, <anno>MQD</anno>}</c></tag>
+ <item>
+ <p>Sets the state of the <c>message_queue_data</c> process
+ flag. <c><anno>MQD</anno></c> should be either <c>off_heap</c>,
+ <c>on_heap</c>, or <c>mixed</c>. The default
+ <c>message_queue_data</c> process flag is determined by the
+ <seealso marker="erl#+xmqd"><c>+xmqd</c></seealso> <c>erl</c>
+ command line argument. For more information, see the
+ documentation of
+ <seealso marker="#process_flag_message_queue_data"><c>process_flag(message_queue_data,
+ <anno>MQD</anno>)</c></seealso>.</p>
+ </item>
</taglist>
</desc>
</func>
@@ -5567,6 +5652,8 @@ true</pre>
<name name="spawn_opt" arity="5"/>
<fsummary>Creates a new process with a function as entry point on a given node.</fsummary>
<type name="priority_level"/>
+ <type name="message_queue_data" />
+ <type name="spawn_opt_option" />
<desc>
<p>Returns the process identifier (pid) of a new process started
by the application
@@ -6639,6 +6726,7 @@ ok
<name name="system_info" arity="1" clause_i="65"/>
<name name="system_info" arity="1" clause_i="66"/>
<name name="system_info" arity="1" clause_i="67"/>
+ <name name="system_info" arity="1" clause_i="68"/>
<fsummary>Information about the system.</fsummary>
<desc>
<p>Returns various information about the current system
@@ -7044,7 +7132,17 @@ ok
used by the runtime system. It is on the form
"&lt;major ver&gt;.&lt;minor ver&gt;".</p>
</item>
- <tag><c>otp_release</c></tag>
+ <tag><marker id="system_info_message_queue_data"><c>message_queue_data</c></marker></tag>
+ <item>
+ <p>Returns the default value of the <c>message_queue_data</c>
+ process flag which is either <c>off_heap</c>, <c>on_heap</c>, or <c>mixed</c>.
+ This default is set by the <c>erl</c> command line argument
+ <seealso marker="erl#+xmqd"><c>+xmqd</c></seealso>. For more information on the
+ <c>message_queue_data</c> process flag, see documentation of
+ <seealso marker="#process_flag_message_queue_data"><c>process_flag(message_queue_data,
+ MQD)</c></seealso>.</p>
+ </item>
+ <tag><marker id="system_info_otp_release"><c>otp_release</c></marker></tag>
<item>
<marker id="system_info_otp_release"></marker>
<p>Returns a string containing the OTP release number of the
@@ -7877,9 +7975,9 @@ timestamp() ->
Secs = ErlangSystemTime div 1000000 - MegaSecs*1000000,
MicroSecs = ErlangSystemTime rem 1000000,
{MegaSecs, Secs, MicroSecs}.</code>
- <p>The BIF uses a native implementation which does
- not build garbage on the heap and with slightly better
- performance.</p>
+ <p>It, however, uses a native implementation which does
+ not build garbage on the heap and with slightly better
+ performance.</p>
<note><p>This time is <em>not</em> a monotonically increasing time
in the general case. For more information, see the documentation of
@@ -8227,7 +8325,7 @@ timestamp() ->
<tag><c>bin_old_vheap_size</c></tag>
<item>The total size of unique off-heap binaries referenced
from the process old heap.</item>
- <tag><c>bin_vheap_block_size</c></tag>
+ <tag><c>bin_old_vheap_block_size</c></tag>
<item>The total size of binaries allowed in the virtual
old heap in the process before doing a garbage collection.</item>
</taglist>
@@ -8812,8 +8910,8 @@ timestamp() ->
true
end</code>
<note>
- <p>Before OTP R11B (<c>ERTS</c> 5.5) <c>unlink/1</c>
- behaved asynchronous, that is, the link was active
+ <p>Prior to OTP release R11B (ERTS version 5.5) <c>unlink/1</c>
+ behaved completely asynchronously, i.e., the link was active
until the "unlink signal" reached the linked entity. This
had an undesirable effect, as you could never know when
you were guaranteed <em>not</em> to be effected by the link.</p>
diff --git a/erts/doc/src/init.xml b/erts/doc/src/init.xml
index fe26df61f7..2a33096d04 100644
--- a/erts/doc/src/init.xml
+++ b/erts/doc/src/init.xml
@@ -247,10 +247,7 @@
<c>Expr</c> during system initialization. If any of these
steps fail (syntax error, parse error or exception during
evaluation), Erlang stops with an error message. Here is an
- example that seeds the random number generator:</p>
- <pre>
-% <input>erl -eval '{X,Y,Z} = now(), random:seed(X,Y,Z).'</input></pre>
- <p>This example uses Erlang as a hexadecimal calculator:</p>
+ example that uses Erlang as a hexadecimal calculator:</p>
<pre>
% <input>erl -noshell -eval 'R = 16#1F+16#A0, io:format("~.16B~n", [R])' \\</input>
<input>-s erlang halt</input>
diff --git a/erts/doc/src/notes.xml b/erts/doc/src/notes.xml
index f27e73b9d3..5a65115cb2 100644
--- a/erts/doc/src/notes.xml
+++ b/erts/doc/src/notes.xml
@@ -31,8 +31,8 @@
</header>
<p>This document describes the changes made to the ERTS application.</p>
-<section><title>Erts 7.1</title>
+<section><title>Erts 7.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
<item>
@@ -981,6 +981,42 @@
</section>
+<section><title>Erts 6.4.1.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fixed a bug that could cause a crash dump to become
+ almost empty.</p>
+ <p>
+ Own Id: OTP-13150</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erts 6.4.1.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ The 'raw' socket option could not be used multiple times
+ in one call to any e.g gen_tcp function because only one
+ of the occurrences were used. This bug has been fixed,
+ and also a small bug concerning propagating error codes
+ from within inet:setopts/2.</p>
+ <p>
+ Own Id: OTP-11482 Aux Id: seq12872 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+
<section><title>Erts 6.4.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/erts/emulator/beam/atom.h b/erts/emulator/beam/atom.h
index ead56c83d8..2c002ca92f 100644
--- a/erts/emulator/beam/atom.h
+++ b/erts/emulator/beam/atom.h
@@ -129,6 +129,7 @@ typedef enum {
(erts_is_atom_utf8_bytes((byte *) LSTR, sizeof(LSTR) - 1, (TERM)))
#define ERTS_DECL_AM(S) Eterm AM_ ## S = am_atom_put(#S, sizeof(#S) - 1)
#define ERTS_INIT_AM(S) AM_ ## S = am_atom_put(#S, sizeof(#S) - 1)
+#define ERTS_MAKE_AM(Str) am_atom_put(Str, sizeof(Str) - 1)
int atom_table_size(void); /* number of elements */
int atom_table_sz(void); /* table size in bytes, excluding stored objects */
diff --git a/erts/emulator/beam/atom.names b/erts/emulator/beam/atom.names
index f20d99f114..13c2a0f8f9 100644
--- a/erts/emulator/beam/atom.names
+++ b/erts/emulator/beam/atom.names
@@ -351,6 +351,7 @@ atom memory_internal
atom memory_types
atom message
atom message_binary
+atom message_queue_data
atom message_queue_len
atom messages
atom merge_trap
@@ -362,6 +363,7 @@ atom min_heap_size
atom min_bin_vheap_size
atom minor_version
atom Minus='-'
+atom mixed
atom module
atom module_info
atom monitored_by
@@ -424,10 +426,12 @@ atom notify
atom notsup
atom nouse_stdio
atom objects
+atom off_heap
atom offset
atom ok
atom old_heap_block_size
atom old_heap_size
+atom on_heap
atom on_load
atom open
atom open_error
diff --git a/erts/emulator/beam/beam_bif_load.c b/erts/emulator/beam/beam_bif_load.c
index 11508a1b39..6b6c066211 100644
--- a/erts/emulator/beam/beam_bif_load.c
+++ b/erts/emulator/beam/beam_bif_load.c
@@ -40,7 +40,7 @@
static void set_default_trace_pattern(Eterm module);
static Eterm check_process_code(Process* rp, Module* modp, int allow_gc, int *redsp);
static void delete_code(Module* modp);
-static void decrement_refc(BeamInstr* code);
+static void decrement_refc(BeamCodeHeader*);
static int any_heap_ref_ptrs(Eterm* start, Eterm* end, char* mod_start, Uint mod_size);
static int any_heap_refs(Eterm* start, Eterm* end, char* mod_start, Uint mod_size);
@@ -58,8 +58,8 @@ BIF_RETTYPE code_is_module_native_1(BIF_ALIST_1)
return am_undefined;
}
erts_rlock_old_code(code_ix);
- res = (erts_is_module_native(modp->curr.code) ||
- erts_is_module_native(modp->old.code)) ?
+ res = (erts_is_module_native(modp->curr.code_hdr) ||
+ erts_is_module_native(modp->old.code_hdr)) ?
am_true : am_false;
erts_runlock_old_code(code_ix);
return res;
@@ -81,7 +81,7 @@ BIF_RETTYPE code_make_stub_module_3(BIF_ALIST_3)
modp = erts_get_module(BIF_ARG_1, erts_active_code_ix());
if (modp && modp->curr.num_breakpoints > 0) {
- ASSERT(modp->curr.code != NULL);
+ ASSERT(modp->curr.code_hdr != NULL);
erts_clear_module_break(modp);
ASSERT(modp->curr.num_breakpoints == 0);
}
@@ -154,7 +154,7 @@ static struct /* Protected by code_write_permission */
{
Process* stager;
ErtsThrPrgrLaterOp lop;
-}commiter_state;
+} committer_state;
#endif
static Eterm
@@ -281,7 +281,7 @@ finish_loading_1(BIF_ALIST_1)
exceptions = 0;
for (i = 0; i < n; i++) {
p[i].exception = 0;
- if (p[i].modp->curr.code && p[i].modp->old.code) {
+ if (p[i].modp->curr.code_hdr && p[i].modp->old.code_hdr) {
p[i].exception = 1;
exceptions++;
}
@@ -367,9 +367,9 @@ staging_epilogue(Process* c_p, int commit, Eterm res, int is_blocking,
* schedulers to read active code_ix in a safe way while executing
* without any memory barriers at all.
*/
- ASSERT(commiter_state.stager == NULL);
- commiter_state.stager = c_p;
- erts_schedule_thr_prgr_later_op(smp_code_ix_commiter, NULL, &commiter_state.lop);
+ ASSERT(committer_state.stager == NULL);
+ committer_state.stager = c_p;
+ erts_schedule_thr_prgr_later_op(smp_code_ix_commiter, NULL, &committer_state.lop);
erts_proc_inc_refc(c_p);
erts_suspend(c_p, ERTS_PROC_LOCK_MAIN, NULL);
/*
@@ -385,11 +385,11 @@ staging_epilogue(Process* c_p, int commit, Eterm res, int is_blocking,
#ifdef ERTS_SMP
static void smp_code_ix_commiter(void* null)
{
- Process* p = commiter_state.stager;
+ Process* p = committer_state.stager;
erts_commit_staging_code_ix();
#ifdef DEBUG
- commiter_state.stager = NULL;
+ committer_state.stager = NULL;
#endif
erts_release_code_write_permission();
erts_smp_proc_lock(p, ERTS_PROC_LOCK_STATUS);
@@ -417,7 +417,7 @@ check_old_code_1(BIF_ALIST_1)
modp = erts_get_module(BIF_ARG_1, code_ix);
if (modp != NULL) {
erts_rlock_old_code(code_ix);
- if (modp->old.code != NULL) {
+ if (modp->old.code_hdr) {
res = am_true;
}
erts_runlock_old_code(code_ix);
@@ -441,7 +441,7 @@ erts_check_process_code(Process *c_p, Eterm module, int allow_gc, int *redsp)
if (!modp)
return am_false;
erts_rlock_old_code(code_ix);
- res = modp->old.code ? check_process_code(c_p, modp, allow_gc, redsp) : am_false;
+ res = modp->old.code_hdr ? check_process_code(c_p, modp, allow_gc, redsp) : am_false;
erts_runlock_old_code(code_ix);
return res;
@@ -525,7 +525,7 @@ BIF_RETTYPE delete_module_1(BIF_ALIST_1)
if (!modp) {
res = am_undefined;
}
- else if (modp->old.code != 0) {
+ else if (modp->old.code_hdr) {
erts_dsprintf_buf_t *dsbufp = erts_create_logger_dsbuf();
erts_dsprintf(dsbufp, "Module %T must be purged before loading\n",
BIF_ARG_1);
@@ -563,8 +563,8 @@ BIF_RETTYPE module_loaded_1(BIF_ALIST_1)
}
code_ix = erts_active_code_ix();
if ((modp = erts_get_module(BIF_ARG_1, code_ix)) != NULL) {
- if (modp->curr.code != NULL
- && modp->curr.code[MI_ON_LOAD_FUNCTION_PTR] == 0) {
+ if (modp->curr.code_hdr
+ && modp->curr.code_hdr->on_load_function_ptr == NULL) {
res = am_true;
}
}
@@ -611,8 +611,8 @@ BIF_RETTYPE call_on_load_function_1(BIF_ALIST_1)
{
Module* modp = erts_get_module(BIF_ARG_1, erts_active_code_ix());
- if (modp && modp->curr.code) {
- BIF_TRAP_CODE_PTR_0(BIF_P, modp->curr.code[MI_ON_LOAD_FUNCTION_PTR]);
+ if (modp && modp->curr.code_hdr) {
+ BIF_TRAP_CODE_PTR_0(BIF_P, modp->curr.code_hdr->on_load_function_ptr);
}
else {
BIF_ERROR(BIF_P, BADARG);
@@ -623,7 +623,6 @@ BIF_RETTYPE finish_after_on_load_2(BIF_ALIST_2)
{
ErtsCodeIndex code_ix;
Module* modp;
- Eterm on_load;
if (!erts_try_seize_code_write_permission(BIF_P)) {
ERTS_BIF_YIELD2(bif_export[BIF_finish_after_on_load_2],
@@ -638,14 +637,14 @@ BIF_RETTYPE finish_after_on_load_2(BIF_ALIST_2)
code_ix = erts_active_code_ix();
modp = erts_get_module(BIF_ARG_1, code_ix);
- if (!modp || modp->curr.code == 0) {
+ if (!modp || !modp->curr.code_hdr) {
error:
erts_smp_thr_progress_unblock();
erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
erts_release_code_write_permission();
BIF_ERROR(BIF_P, BADARG);
}
- if ((on_load = modp->curr.code[MI_ON_LOAD_FUNCTION_PTR]) == 0) {
+ if (modp->curr.code_hdr->on_load_function_ptr == NULL) {
goto error;
}
if (BIF_ARG_2 != am_false && BIF_ARG_2 != am_true) {
@@ -667,7 +666,7 @@ BIF_RETTYPE finish_after_on_load_2(BIF_ALIST_2)
ep->code[4] = 0;
}
}
- modp->curr.code[MI_ON_LOAD_FUNCTION_PTR] = 0;
+ modp->curr.code_hdr->on_load_function_ptr = NULL;
set_default_trace_pattern(BIF_ARG_1);
} else if (BIF_ARG_2 == am_false) {
BeamInstr* code;
@@ -679,13 +678,16 @@ BIF_RETTYPE finish_after_on_load_2(BIF_ALIST_2)
* the current code; the old code is not touched.
*/
erts_total_code_size -= modp->curr.code_length;
- code = modp->curr.code;
- end = (BeamInstr *)((char *)code + modp->curr.code_length);
+ code = (BeamInstr*) modp->curr.code_hdr;
+ end = (BeamInstr *) ((char *)code + modp->curr.code_length);
erts_cleanup_funs_on_purge(code, end);
beam_catches_delmod(modp->curr.catches, code, modp->curr.code_length,
erts_active_code_ix());
- erts_free(ERTS_ALC_T_CODE, (void *) code);
- modp->curr.code = NULL;
+ if (modp->curr.code_hdr->literals_start) {
+ erts_free(ERTS_ALC_T_LITERAL, modp->curr.code_hdr->literals_start);
+ }
+ erts_free(ERTS_ALC_T_CODE, modp->curr.code_hdr);
+ modp->curr.code_hdr = NULL;
modp->curr.code_length = 0;
modp->curr.catches = BEAM_CATCHES_NIL;
erts_remove_from_ranges(code);
@@ -721,31 +723,50 @@ set_default_trace_pattern(Eterm module)
}
}
+static ERTS_INLINE int
+check_mod_funs(Process *p, ErlOffHeap *off_heap, char *area, size_t area_size)
+{
+ struct erl_off_heap_header* oh;
+ for (oh = off_heap->first; oh; oh = oh->next) {
+ if (thing_subtag(oh->thing_word) == FUN_SUBTAG) {
+ ErlFunThing* funp = (ErlFunThing*) oh;
+ if (ErtsInArea(funp->fe->address, area, area_size))
+ return !0;
+ }
+ }
+ return 0;
+}
+
+
static Eterm
check_process_code(Process* rp, Module* modp, int allow_gc, int *redsp)
{
BeamInstr* start;
+ char* literals;
+ Uint lit_bsize;
char* mod_start;
Uint mod_size;
- BeamInstr* end;
Eterm* sp;
- struct erl_off_heap_header* oh;
int done_gc = 0;
+ int need_gc = 0;
+ ErtsMessage *msgp;
+ ErlHeapFragment *hfrag;
-#define INSIDE(a) (start <= (a) && (a) < end)
+#define ERTS_ORDINARY_GC__ (1 << 0)
+#define ERTS_LITERAL_GC__ (1 << 1)
/*
* Pick up limits for the module.
*/
- start = modp->old.code;
- end = (BeamInstr *)((char *)start + modp->old.code_length);
+ start = (BeamInstr*) modp->old.code_hdr;
mod_start = (char *) start;
mod_size = modp->old.code_length;
/*
* Check if current instruction or continuation pointer points into module.
*/
- if (INSIDE(rp->i) || INSIDE(rp->cp)) {
+ if (ErtsInArea(rp->i, mod_start, mod_size)
+ || ErtsInArea(rp->cp, mod_start, mod_size)) {
return am_true;
}
@@ -753,7 +774,7 @@ check_process_code(Process* rp, Module* modp, int allow_gc, int *redsp)
* Check all continuation pointers stored on the stack.
*/
for (sp = rp->stop; sp < STACK_START(rp); sp++) {
- if (is_CP(*sp) && INSIDE(cp_val(*sp))) {
+ if (is_CP(*sp) && ErtsInArea(cp_val(*sp), mod_start, mod_size)) {
return am_true;
}
}
@@ -767,15 +788,15 @@ check_process_code(Process* rp, Module* modp, int allow_gc, int *redsp)
struct StackTrace *s;
ASSERT(is_list(rp->ftrace));
s = (struct StackTrace *) big_val(CDR(list_val(rp->ftrace)));
- if ((s->pc && INSIDE(s->pc)) ||
- (s->current && INSIDE(s->current))) {
+ if ((s->pc && ErtsInArea(s->pc, mod_start, mod_size)) ||
+ (s->current && ErtsInArea(s->current, mod_start, mod_size))) {
rp->freason = EXC_NULL;
rp->fvalue = NIL;
rp->ftrace = NIL;
} else {
int i;
for (i = 0; i < s->depth; i++) {
- if (INSIDE(s->trace[i])) {
+ if (ErtsInArea(s->trace[i], mod_start, mod_size)) {
rp->freason = EXC_NULL;
rp->fvalue = NIL;
rp->ftrace = NIL;
@@ -796,111 +817,141 @@ check_process_code(Process* rp, Module* modp, int allow_gc, int *redsp)
}
/*
- * See if there are funs that refer to the old version of the module.
+ * Message queue can contains funs, but (at least currently) no
+ * constants. If we got references to this module from the message
+ * queue, a GC cannot remove these...
*/
- rescan:
- for (oh = MSO(rp).first; oh; oh = oh->next) {
- if (thing_subtag(oh->thing_word) == FUN_SUBTAG) {
- ErlFunThing* funp = (ErlFunThing*) oh;
+ erts_smp_proc_lock(rp, ERTS_PROC_LOCK_MSGQ);
+ ERTS_SMP_MSGQ_MV_INQ2PRIVQ(rp);
+ erts_smp_proc_unlock(rp, ERTS_PROC_LOCK_MSGQ);
- if (INSIDE((BeamInstr *) funp->fe->address)) {
- if (done_gc) {
- return am_true;
- } else {
- if (!allow_gc)
- return am_aborted;
- /*
- * Try to get rid of this fun by garbage collecting.
- * Clear both fvalue and ftrace to make sure they
- * don't hold any funs.
- */
- rp->freason = EXC_NULL;
- rp->fvalue = NIL;
- rp->ftrace = NIL;
- done_gc = 1;
- FLAGS(rp) |= F_NEED_FULLSWEEP;
- *redsp += erts_garbage_collect(rp, 0, rp->arg_reg, rp->arity);
- goto rescan;
- }
- }
+ for (msgp = rp->msg.first; msgp; msgp = msgp->next) {
+ if (msgp->data.attached == ERTS_MSG_COMBINED_HFRAG)
+ hfrag = &msgp->hfrag;
+ else if (is_value(ERL_MESSAGE_TERM(msgp)) && msgp->data.heap_frag)
+ hfrag = msgp->data.heap_frag;
+ else
+ continue;
+ for (; hfrag; hfrag = hfrag->next) {
+ if (check_mod_funs(rp, &hfrag->off_heap, mod_start, mod_size))
+ return am_true;
+ /* Should not contain any constants... */
+ ASSERT(!any_heap_ref_ptrs(&hfrag->mem[0],
+ &hfrag->mem[hfrag->used_size],
+ mod_start,
+ mod_size));
}
}
- /*
- * See if there are constants inside the module referenced by the process.
- */
- done_gc = 0;
- for (;;) {
- ErlMessage* mp;
+ literals = (char*) modp->old.code_hdr->literals_start;
+ lit_bsize = (char*) modp->old.code_hdr->literals_end - literals;
+
+ while (1) {
- if (any_heap_ref_ptrs(&rp->fvalue, &rp->fvalue+1, mod_start, mod_size)) {
+ /* Check heap, stack etc... */
+ if (check_mod_funs(rp, &rp->off_heap, mod_start, mod_size))
+ goto try_gc;
+ if (any_heap_ref_ptrs(&rp->fvalue, &rp->fvalue+1, literals, lit_bsize)) {
rp->freason = EXC_NULL;
rp->fvalue = NIL;
rp->ftrace = NIL;
}
- if (any_heap_ref_ptrs(rp->stop, rp->hend, mod_start, mod_size)) {
- goto need_gc;
- }
- if (any_heap_refs(rp->heap, rp->htop, mod_start, mod_size)) {
- goto need_gc;
- }
+ if (any_heap_ref_ptrs(rp->stop, rp->hend, literals, lit_bsize))
+ goto try_literal_gc;
+ if (any_heap_refs(rp->heap, rp->htop, literals, lit_bsize))
+ goto try_literal_gc;
+ if (any_heap_refs(rp->old_heap, rp->old_htop, literals, lit_bsize))
+ goto try_literal_gc;
+
+ /* Check dictionary */
+ if (rp->dictionary) {
+ Eterm* start = rp->dictionary->data;
+ Eterm* end = start + rp->dictionary->used;
- if (any_heap_refs(rp->old_heap, rp->old_htop, mod_start, mod_size)) {
- goto need_gc;
+ if (any_heap_ref_ptrs(start, end, literals, lit_bsize))
+ goto try_literal_gc;
}
- if (rp->dictionary != NULL) {
- Eterm* start = rp->dictionary->data;
- Eterm* end = start + rp->dictionary->used;
+ /* Check heap fragments */
+ for (hfrag = rp->mbuf; hfrag; hfrag = hfrag->next) {
+ Eterm *hp, *hp_end;
+ /* Off heap lists should already have been moved into process */
+ ASSERT(!check_mod_funs(rp, &hfrag->off_heap, mod_start, mod_size));
- if (any_heap_ref_ptrs(start, end, mod_start, mod_size)) {
- goto need_gc;
- }
+ hp = &hfrag->mem[0];
+ hp_end = &hfrag->mem[hfrag->used_size];
+ if (any_heap_ref_ptrs(hp, hp_end, mod_start, lit_bsize))
+ goto try_literal_gc;
}
- for (mp = rp->msg.first; mp != NULL; mp = mp->next) {
- if (any_heap_ref_ptrs(mp->m, mp->m+2, mod_start, mod_size)) {
- goto need_gc;
+#ifdef DEBUG
+ /*
+ * Message buffer fragments should not have any references
+ * to constants, and off heap lists should already have
+ * been moved into process off heap structure.
+ */
+ for (msgp = rp->msg_frag; msgp; msgp = msgp->next) {
+ if (msgp->data.attached == ERTS_MSG_COMBINED_HFRAG)
+ hfrag = &msgp->hfrag;
+ else
+ hfrag = msgp->data.heap_frag;
+ for (; hfrag; hfrag = hfrag->next) {
+ Eterm *hp, *hp_end;
+ ASSERT(!check_mod_funs(rp, &hfrag->off_heap, mod_start, mod_size));
+
+ hp = &hfrag->mem[0];
+ hp_end = &hfrag->mem[hfrag->used_size];
+ ASSERT(!any_heap_ref_ptrs(hp, hp_end, mod_start, lit_bsize));
}
}
- break;
- need_gc:
- if (done_gc) {
+#endif
+
+ return am_false;
+
+ try_literal_gc:
+ need_gc |= ERTS_LITERAL_GC__;
+
+ try_gc:
+ need_gc |= ERTS_ORDINARY_GC__;
+
+ if ((done_gc & need_gc) == need_gc)
return am_true;
- } else {
- Eterm* literals;
- Uint lit_size;
- struct erl_off_heap_header* oh;
- if (!allow_gc)
- return am_aborted;
+ if (!allow_gc)
+ return am_aborted;
- /*
- * Try to get rid of constants by by garbage collecting.
- * Clear both fvalue and ftrace.
- */
- rp->freason = EXC_NULL;
- rp->fvalue = NIL;
- rp->ftrace = NIL;
- done_gc = 1;
+ need_gc &= ~done_gc;
+
+ /*
+ * Try to get rid of constants by by garbage collecting.
+ * Clear both fvalue and ftrace.
+ */
+
+ rp->freason = EXC_NULL;
+ rp->fvalue = NIL;
+ rp->ftrace = NIL;
+
+ if (need_gc & ERTS_ORDINARY_GC__) {
FLAGS(rp) |= F_NEED_FULLSWEEP;
- *redsp += erts_garbage_collect(rp, 0, rp->arg_reg, rp->arity);
- literals = (Eterm *) modp->old.code[MI_LITERALS_START];
- lit_size = (Eterm *) modp->old.code[MI_LITERALS_END] - literals;
- oh = (struct erl_off_heap_header *)
- modp->old.code[MI_LITERALS_OFF_HEAP];
- *redsp += lit_size / 10; /* Need, better value... */
- erts_garbage_collect_literals(rp, literals, lit_size, oh);
+ *redsp += erts_garbage_collect_nobump(rp, 0, rp->arg_reg, rp->arity);
+ done_gc |= ERTS_ORDINARY_GC__;
}
+ if (need_gc & ERTS_LITERAL_GC__) {
+ struct erl_off_heap_header* oh;
+ oh = modp->old.code_hdr->literals_off_heap;
+ *redsp += lit_bsize / 64; /* Need, better value... */
+ erts_garbage_collect_literals(rp, (Eterm*)literals, lit_bsize, oh);
+ done_gc |= ERTS_LITERAL_GC__;
+ }
+ need_gc = 0;
}
- return am_false;
-#undef INSIDE
-}
-#define in_area(ptr,start,nbytes) \
- ((UWord)((char*)(ptr) - (char*)(start)) < (nbytes))
+#undef ERTS_ORDINARY_GC__
+#undef ERTS_LITERAL_GC__
+
+}
static int
any_heap_ref_ptrs(Eterm* start, Eterm* end, char* mod_start, Uint mod_size)
@@ -913,7 +964,7 @@ any_heap_ref_ptrs(Eterm* start, Eterm* end, char* mod_start, Uint mod_size)
switch (primary_tag(val)) {
case TAG_PRIMARY_BOXED:
case TAG_PRIMARY_LIST:
- if (in_area(val, mod_start, mod_size)) {
+ if (ErtsInArea(val, mod_start, mod_size)) {
return 1;
}
break;
@@ -933,7 +984,7 @@ any_heap_refs(Eterm* start, Eterm* end, char* mod_start, Uint mod_size)
switch (primary_tag(val)) {
case TAG_PRIMARY_BOXED:
case TAG_PRIMARY_LIST:
- if (in_area(val, mod_start, mod_size)) {
+ if (ErtsInArea(val, mod_start, mod_size)) {
return 1;
}
break;
@@ -943,7 +994,7 @@ any_heap_refs(Eterm* start, Eterm* end, char* mod_start, Uint mod_size)
if (header_is_bin_matchstate(val)) {
ErlBinMatchState *ms = (ErlBinMatchState*) p;
ErlBinMatchBuffer *mb = &(ms->mb);
- if (in_area(mb->orig, mod_start, mod_size)) {
+ if (ErtsInArea(mb->orig, mod_start, mod_size)) {
return 1;
}
}
@@ -958,6 +1009,91 @@ any_heap_refs(Eterm* start, Eterm* end, char* mod_start, Uint mod_size)
#undef in_area
+#ifdef ERTS_SMP
+static void copy_literals_commit(void*);
+#endif
+
+copy_literals_t erts_clrange = {NULL, 0};
+
+/* copy literals
+ *
+ * copy_literals.ptr = LitPtr
+ * copy_literals.sz = LitSz
+ * ------ THR PROG COMMIT -----
+ *
+ * - check process code
+ * - check process code
+ * ...
+ * copy_literals.ptr = NULL
+ * copy_literals.sz = 0
+ * ------ THR PROG COMMIT -----
+ * ...
+ */
+
+
+BIF_RETTYPE copy_literals_2(BIF_ALIST_2)
+{
+ Module* modp;
+ ErtsCodeIndex code_ix;
+ Eterm res = am_true;
+
+ if (is_not_atom(BIF_ARG_1) || (am_true != BIF_ARG_2 && am_false != BIF_ARG_2)) {
+ BIF_ERROR(BIF_P, BADARG);
+ }
+
+ if (!erts_try_seize_code_write_permission(BIF_P)) {
+ ERTS_BIF_YIELD2(bif_export[BIF_copy_literals_2], BIF_P, BIF_ARG_1, BIF_ARG_2);
+ }
+
+ code_ix = erts_active_code_ix();
+
+ if ((modp = erts_get_module(BIF_ARG_1, code_ix)) == NULL || !modp->old.code_hdr) {
+ res = am_false;
+ goto done;
+ }
+
+ if (BIF_ARG_2 == am_true) {
+ if (erts_clrange.ptr != NULL) {
+ res = am_aborted;
+ goto done;
+ }
+ erts_clrange.ptr = (Eterm*) modp->old.code_hdr->literals_start;
+ erts_clrange.sz = (Eterm*) modp->old.code_hdr->literals_end - erts_clrange.ptr;
+ } else if (BIF_ARG_2 == am_false) {
+ erts_clrange.ptr = NULL;
+ erts_clrange.sz = 0;
+ }
+
+#ifdef ERTS_SMP
+ ASSERT(committer_state.stager == NULL);
+ committer_state.stager = BIF_P;
+ erts_schedule_thr_prgr_later_op(copy_literals_commit, NULL, &committer_state.lop);
+ erts_proc_inc_refc(BIF_P);
+ erts_suspend(BIF_P, ERTS_PROC_LOCK_MAIN, NULL);
+ ERTS_BIF_YIELD_RETURN(BIF_P, am_true);
+#endif
+done:
+ erts_release_code_write_permission();
+ BIF_RET(res);
+}
+
+#ifdef ERTS_SMP
+static void copy_literals_commit(void* null) {
+ Process* p = committer_state.stager;
+#ifdef DEBUG
+ committer_state.stager = NULL;
+#endif
+ erts_release_code_write_permission();
+ erts_smp_proc_lock(p, ERTS_PROC_LOCK_STATUS);
+ if (!ERTS_PROC_IS_EXITING(p)) {
+ erts_resume(p, ERTS_PROC_LOCK_STATUS);
+ }
+ erts_smp_proc_unlock(p, ERTS_PROC_LOCK_STATUS);
+ erts_proc_dec_refc(p);
+}
+#endif /* ERTS_SMP */
+
+
BIF_RETTYPE purge_module_1(BIF_ALIST_1)
{
ErtsCodeIndex code_ix;
@@ -990,7 +1126,7 @@ BIF_RETTYPE purge_module_1(BIF_ALIST_1)
/*
* Any code to purge?
*/
- if (modp->old.code == 0) {
+ if (!modp->old.code_hdr) {
ERTS_BIF_PREP_ERROR(ret, BIF_P, BADARG);
}
else {
@@ -1013,14 +1149,17 @@ BIF_RETTYPE purge_module_1(BIF_ALIST_1)
*/
ASSERT(erts_total_code_size >= modp->old.code_length);
erts_total_code_size -= modp->old.code_length;
- code = modp->old.code;
+ code = (BeamInstr*) modp->old.code_hdr;
end = (BeamInstr *)((char *)code + modp->old.code_length);
erts_cleanup_funs_on_purge(code, end);
beam_catches_delmod(modp->old.catches, code, modp->old.code_length,
code_ix);
- decrement_refc(code);
+ decrement_refc(modp->old.code_hdr);
+ if (modp->old.code_hdr->literals_start) {
+ erts_free(ERTS_ALC_T_LITERAL, modp->old.code_hdr->literals_start);
+ }
erts_free(ERTS_ALC_T_CODE, (void *) code);
- modp->old.code = NULL;
+ modp->old.code_hdr = NULL;
modp->old.code_length = 0;
modp->old.catches = BEAM_CATCHES_NIL;
erts_remove_from_ranges(code);
@@ -1037,10 +1176,9 @@ BIF_RETTYPE purge_module_1(BIF_ALIST_1)
}
static void
-decrement_refc(BeamInstr* code)
+decrement_refc(BeamCodeHeader* code_hdr)
{
- struct erl_off_heap_header* oh =
- (struct erl_off_heap_header *) code[MI_LITERALS_OFF_HEAP];
+ struct erl_off_heap_header* oh = code_hdr->literals_off_heap;
while (oh) {
Binary* bptr;
@@ -1089,7 +1227,7 @@ delete_code(Module* modp)
ASSERT(modp->curr.num_breakpoints == 0);
ASSERT(modp->curr.num_traced_exports == 0);
modp->old = modp->curr;
- modp->curr.code = NULL;
+ modp->curr.code_hdr = NULL;
modp->curr.code_length = 0;
modp->curr.catches = BEAM_CATCHES_NIL;
modp->curr.nif = NULL;
@@ -1106,9 +1244,9 @@ beam_make_current_old(Process *c_p, ErtsProcLocks c_p_locks, Eterm module)
* if not, delete old code; error if old code already exists.
*/
- if (modp->curr.code != NULL && modp->old.code != NULL) {
+ if (modp->curr.code_hdr && modp->old.code_hdr) {
return am_not_purged;
- } else if (modp->old.code == NULL) { /* Make the current version old. */
+ } else if (!modp->old.code_hdr) { /* Make the current version old. */
delete_code(modp);
}
return NIL;
diff --git a/erts/emulator/beam/beam_bp.c b/erts/emulator/beam/beam_bp.c
index 016d0aaa32..2a8663d7ee 100644
--- a/erts/emulator/beam/beam_bp.c
+++ b/erts/emulator/beam/beam_bp.c
@@ -152,8 +152,8 @@ erts_bp_match_functions(BpFunctions* f, Eterm mfa[3], int specified)
num_modules = 0;
for (current = 0; current < max_modules; current++) {
modp = module_code(current, code_ix);
- if (modp->curr.code) {
- max_funcs += modp->curr.code[MI_NUM_FUNCTIONS];
+ if (modp->curr.code_hdr) {
+ max_funcs += modp->curr.code_hdr->num_functions;
module[num_modules++] = modp;
}
}
@@ -161,9 +161,9 @@ erts_bp_match_functions(BpFunctions* f, Eterm mfa[3], int specified)
f->matching = (BpFunction *) Alloc(max_funcs*sizeof(BpFunction));
i = 0;
for (current = 0; current < num_modules; current++) {
- BeamInstr** code_base = (BeamInstr **) module[current]->curr.code;
+ BeamCodeHeader* code_hdr = module[current]->curr.code_hdr;
BeamInstr* code;
- Uint num_functions = (Uint)(UWord) code_base[MI_NUM_FUNCTIONS];
+ Uint num_functions = (Uint)(UWord) code_hdr->num_functions;
Uint fi;
if (specified > 0) {
@@ -177,7 +177,7 @@ erts_bp_match_functions(BpFunctions* f, Eterm mfa[3], int specified)
BeamInstr* pc;
int wi;
- code = code_base[MI_FUNCTIONS+fi];
+ code = code_hdr->functions[fi];
ASSERT(code[0] == (BeamInstr) BeamOp(op_i_func_info_IaaI));
pc = code+5;
if (erts_is_native_break(pc)) {
@@ -547,21 +547,21 @@ erts_clear_all_breaks(BpFunctions* f)
int
erts_clear_module_break(Module *modp) {
- BeamInstr** code_base;
+ BeamCodeHeader* code_hdr;
Uint n;
Uint i;
ERTS_SMP_LC_ASSERT(erts_smp_thr_progress_is_blocking());
ASSERT(modp);
- code_base = (BeamInstr **) modp->curr.code;
- if (code_base == NULL) {
+ code_hdr = modp->curr.code_hdr;
+ if (!code_hdr) {
return 0;
}
- n = (Uint)(UWord) code_base[MI_NUM_FUNCTIONS];
+ n = (Uint)(UWord) code_hdr->num_functions;
for (i = 0; i < n; ++i) {
BeamInstr* pc;
- pc = code_base[MI_FUNCTIONS+i] + 5;
+ pc = code_hdr->functions[i] + 5;
if (erts_is_native_break(pc)) {
continue;
}
@@ -573,7 +573,7 @@ erts_clear_module_break(Module *modp) {
for (i = 0; i < n; ++i) {
BeamInstr* pc;
- pc = code_base[MI_FUNCTIONS+i] + 5;
+ pc = code_hdr->functions[i] + 5;
if (erts_is_native_break(pc)) {
continue;
}
@@ -1204,17 +1204,17 @@ int erts_is_time_break(Process *p, BeamInstr *pc, Eterm *retval) {
BeamInstr *
erts_find_local_func(Eterm mfa[3]) {
Module *modp;
- BeamInstr** code_base;
+ BeamCodeHeader* code_hdr;
BeamInstr* code_ptr;
Uint i,n;
if ((modp = erts_get_module(mfa[0], erts_active_code_ix())) == NULL)
return NULL;
- if ((code_base = (BeamInstr **) modp->curr.code) == NULL)
+ if ((code_hdr = modp->curr.code_hdr) == NULL)
return NULL;
- n = (BeamInstr) code_base[MI_NUM_FUNCTIONS];
+ n = (BeamInstr) code_hdr->num_functions;
for (i = 0; i < n; ++i) {
- code_ptr = code_base[MI_FUNCTIONS+i];
+ code_ptr = code_hdr->functions[i];
ASSERT(((BeamInstr) BeamOp(op_i_func_info_IaaI)) == code_ptr[0]);
ASSERT(mfa[0] == ((Eterm) code_ptr[2]) ||
is_nil((Eterm) code_ptr[2]));
diff --git a/erts/emulator/beam/beam_debug.c b/erts/emulator/beam/beam_debug.c
index 0e921d761c..e37bd4d78c 100644
--- a/erts/emulator/beam/beam_debug.c
+++ b/erts/emulator/beam/beam_debug.c
@@ -73,6 +73,40 @@ erts_debug_flat_size_1(BIF_ALIST_1)
}
}
+BIF_RETTYPE
+erts_debug_size_shared_1(BIF_ALIST_1)
+{
+ Process* p = BIF_P;
+ Eterm term = BIF_ARG_1;
+ Uint size = size_shared(term);
+
+ if (IS_USMALL(0, size)) {
+ BIF_RET(make_small(size));
+ } else {
+ Eterm* hp = HAlloc(p, BIG_UINT_HEAP_SIZE);
+ BIF_RET(uint_to_big(size, hp));
+ }
+}
+
+BIF_RETTYPE
+erts_debug_copy_shared_1(BIF_ALIST_1)
+{
+ Process* p = BIF_P;
+ Eterm term = BIF_ARG_1;
+ Uint size;
+ Eterm* hp;
+ Eterm copy;
+ erts_shcopy_t info;
+ INITIALIZE_SHCOPY(info);
+
+ size = copy_shared_calculate(term, &info);
+ if (size > 0) {
+ hp = HAlloc(p, size);
+ }
+ copy = copy_shared_perform(term, size, &info, &hp, &p->off_heap);
+ DESTROY_SHCOPY(info);
+ BIF_RET(copy);
+}
BIF_RETTYPE
erts_debug_breakpoint_2(BIF_ALIST_2)
@@ -208,7 +242,7 @@ erts_debug_disassemble_1(BIF_ALIST_1)
Eterm bin;
Eterm mfa;
BeamInstr* funcinfo = NULL; /* Initialized to eliminate warning. */
- BeamInstr* code_base;
+ BeamCodeHeader* code_hdr;
BeamInstr* code_ptr = NULL; /* Initialized to eliminate warning. */
BeamInstr instr;
BeamInstr uaddr;
@@ -258,12 +292,12 @@ erts_debug_disassemble_1(BIF_ALIST_1)
*/
code_ptr = ((BeamInstr *) ep->addressv[code_ix]) - 5;
funcinfo = code_ptr+2;
- } else if (modp == NULL || (code_base = modp->curr.code) == NULL) {
+ } else if (modp == NULL || (code_hdr = modp->curr.code_hdr) == NULL) {
BIF_RET(am_undef);
} else {
- n = code_base[MI_NUM_FUNCTIONS];
+ n = code_hdr->num_functions;
for (i = 0; i < n; i++) {
- code_ptr = (BeamInstr *) code_base[MI_FUNCTIONS+i];
+ code_ptr = code_hdr->functions[i];
if (code_ptr[3] == name && code_ptr[4] == arity) {
funcinfo = code_ptr+2;
break;
diff --git a/erts/emulator/beam/beam_emu.c b/erts/emulator/beam/beam_emu.c
index faf496a030..4d7b00b032 100644
--- a/erts/emulator/beam/beam_emu.c
+++ b/erts/emulator/beam/beam_emu.c
@@ -237,6 +237,14 @@ void** beam_ops;
HEAP_TOP(c_p) = HTOP; \
c_p->stop = E
+#define HEAVY_SWAPIN \
+ SWAPIN; \
+ FCALLS = c_p->fcalls
+
+#define HEAVY_SWAPOUT \
+ SWAPOUT; \
+ c_p->fcalls = FCALLS
+
/*
* Use LIGHT_SWAPOUT when the called function
* will call HeapOnlyAlloc() (and never HAlloc()).
@@ -297,7 +305,7 @@ void** beam_ops;
if (E - HTOP < (needed + (HeapNeed))) { \
SWAPOUT; \
PROCESS_MAIN_CHK_LOCKS(c_p); \
- FCALLS -= erts_garbage_collect(c_p, needed + (HeapNeed), reg, (M)); \
+ FCALLS -= erts_garbage_collect_nobump(c_p, needed + (HeapNeed), reg, (M)); \
ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p); \
PROCESS_MAIN_CHK_LOCKS(c_p); \
SWAPIN; \
@@ -349,7 +357,7 @@ void** beam_ops;
if ((E - HTOP < need) || (MSO(c_p).overhead + (VNh) >= BIN_VHEAP_SZ(c_p))) {\
SWAPOUT; \
PROCESS_MAIN_CHK_LOCKS(c_p); \
- FCALLS -= erts_garbage_collect(c_p, need, reg, (Live)); \
+ FCALLS -= erts_garbage_collect_nobump(c_p, need, reg, (Live)); \
ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p); \
PROCESS_MAIN_CHK_LOCKS(c_p); \
SWAPIN; \
@@ -370,7 +378,7 @@ void** beam_ops;
if (E - HTOP < need) { \
SWAPOUT; \
PROCESS_MAIN_CHK_LOCKS(c_p); \
- FCALLS -= erts_garbage_collect(c_p, need, reg, (Live)); \
+ FCALLS -= erts_garbage_collect_nobump(c_p, need, reg, (Live));\
ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p); \
PROCESS_MAIN_CHK_LOCKS(c_p); \
SWAPIN; \
@@ -391,7 +399,7 @@ void** beam_ops;
SWAPOUT; \
reg[Live] = Extra; \
PROCESS_MAIN_CHK_LOCKS(c_p); \
- FCALLS -= erts_garbage_collect(c_p, need, reg, (Live)+1); \
+ FCALLS -= erts_garbage_collect_nobump(c_p, need, reg, (Live)+1); \
ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p); \
PROCESS_MAIN_CHK_LOCKS(c_p); \
Extra = reg[Live]; \
@@ -415,9 +423,9 @@ void** beam_ops;
#define MakeFun(FunP, NumFree) \
do { \
- SWAPOUT; \
+ HEAVY_SWAPOUT; \
r(0) = new_fun(c_p, reg, (ErlFunEntry *) FunP, NumFree); \
- SWAPIN; \
+ HEAVY_SWAPIN; \
} while (0)
#define PutTuple(Dst, Arity) \
@@ -1402,11 +1410,11 @@ void process_main(void)
}
live = Arg(2);
- SWAPOUT;
+ HEAVY_SWAPOUT;
reg[live] = increment_reg_val;
reg[live+1] = make_small(increment_val);
result = erts_gc_mixed_plus(c_p, reg, live);
- SWAPIN;
+ HEAVY_SWAPIN;
ERTS_HOLE_CHECK(c_p);
if (is_value(result)) {
StoreBifResult(3, result);
@@ -1420,11 +1428,11 @@ void process_main(void)
Eterm result; \
Uint live = Arg(1); \
\
- SWAPOUT; \
+ HEAVY_SWAPOUT; \
reg[live] = Op1; \
reg[live+1] = Op2; \
result = erts_gc_##name(c_p, reg, live); \
- SWAPIN; \
+ HEAVY_SWAPIN; \
ERTS_HOLE_CHECK(c_p); \
if (is_value(result)) { \
StoreBifResult(4, result); \
@@ -1654,10 +1662,6 @@ void process_main(void)
ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
ERTS_SMP_REQ_PROC_MAIN_LOCK(c_p);
PROCESS_MAIN_CHK_LOCKS(c_p);
- if (c_p->mbuf || MSO(c_p).overhead >= BIN_VHEAP_SZ(c_p)) {
- result = erts_gc_after_bif_call(c_p, result, reg, 2);
- E = c_p->stop;
- }
HTOP = HEAP_TOP(c_p);
FCALLS = c_p->fcalls;
if (is_value(result)) {
@@ -1745,11 +1749,10 @@ void process_main(void)
SWAPIN;
}
/* only x(2) is included in the rootset here */
- if (E - HTOP < 3 || c_p->mbuf) { /* Force GC in case add_stacktrace()
- * created heap fragments */
+ if (E - HTOP < 3) {
SWAPOUT;
PROCESS_MAIN_CHK_LOCKS(c_p);
- FCALLS -= erts_garbage_collect(c_p, 3, reg+2, 1);
+ FCALLS -= erts_garbage_collect_nobump(c_p, 3, reg+2, 1);
ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
PROCESS_MAIN_CHK_LOCKS(c_p);
SWAPIN;
@@ -1833,10 +1836,17 @@ void process_main(void)
OpCase(i_loop_rec_f):
{
BeamInstr *next;
- ErlMessage* msgp;
+ ErtsMessage* msgp;
- loop_rec__:
+ /*
+ * We need to disable GC while matching messages
+ * in the queue. This since messages with data outside
+ * the heap will be corrupted by a GC.
+ */
+ ASSERT(!(c_p->flags & F_DELAY_GC));
+ c_p->flags |= F_DELAY_GC;
+ loop_rec__:
PROCESS_MAIN_CHK_LOCKS(c_p);
msgp = PEEK_MESSAGE(c_p);
@@ -1848,6 +1858,7 @@ void process_main(void)
if (ERTS_PROC_PENDING_EXIT(c_p)) {
erts_smp_proc_unlock(c_p, ERTS_PROC_LOCKS_MSG_RECEIVE);
SWAPOUT;
+ c_p->flags &= ~F_DELAY_GC;
goto do_schedule; /* Will be rescheduled for exit */
}
ERTS_SMP_MSGQ_MV_INQ2PRIVQ(c_p);
@@ -1857,30 +1868,27 @@ void process_main(void)
else
#endif
{
+ c_p->flags &= ~F_DELAY_GC;
SET_I((BeamInstr *) Arg(0));
Goto(*I); /* Jump to a wait or wait_timeout instruction */
}
}
- ErtsMoveMsgAttachmentIntoProc(msgp, c_p, E, HTOP, FCALLS,
- {
- SWAPOUT;
- PROCESS_MAIN_CHK_LOCKS(c_p);
- },
- {
- ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
- PROCESS_MAIN_CHK_LOCKS(c_p);
- SWAPIN;
- });
if (is_non_value(ERL_MESSAGE_TERM(msgp))) {
- /*
- * A corrupt distribution message that we weren't able to decode;
- * remove it...
- */
- ASSERT(!msgp->data.attached);
- /* TODO: Add DTrace probe for this bad message situation? */
- UNLINK_MESSAGE(c_p, msgp);
- free_message(msgp);
- goto loop_rec__;
+ SWAPOUT; /* erts_decode_dist_message() may write to heap... */
+ if (!erts_decode_dist_message(c_p, ERTS_PROC_LOCK_MAIN, msgp, 0)) {
+ /*
+ * A corrupt distribution message that we weren't able to decode;
+ * remove it...
+ */
+ /* No swapin should be needed */
+ ASSERT(HTOP == c_p->htop && E == c_p->stop);
+ /* TODO: Add DTrace probe for this bad message situation? */
+ UNLINK_MESSAGE(c_p, msgp);
+ msgp->next = NULL;
+ erts_cleanup_messages(msgp);
+ goto loop_rec__;
+ }
+ SWAPIN;
}
PreFetch(1, next);
r(0) = ERL_MESSAGE_TERM(msgp);
@@ -1892,8 +1900,7 @@ void process_main(void)
*/
OpCase(remove_message): {
BeamInstr *next;
- ErlMessage* msgp;
-
+ ErtsMessage* msgp;
PROCESS_MAIN_CHK_LOCKS(c_p);
PreFetch(0, next);
@@ -1907,20 +1914,7 @@ void process_main(void)
if (DT_UTAG(c_p) != NIL) {
if (DT_UTAG_FLAGS(c_p) & DT_UTAG_PERMANENT) {
SEQ_TRACE_TOKEN(c_p) = am_have_dt_utag;
-#ifdef DTRACE_TAG_HARDDEBUG
- if (DT_UTAG_FLAGS(c_p) & DT_UTAG_SPREADING)
- erts_fprintf(stderr,
- "Dtrace -> (%T) stop spreading "
- "tag %T with message %T\r\n",
- c_p->common.id,DT_UTAG(c_p),ERL_MESSAGE_TERM(msgp));
-#endif
} else {
-#ifdef DTRACE_TAG_HARDDEBUG
- erts_fprintf(stderr,
- "Dtrace -> (%T) kill tag %T with "
- "message %T\r\n",
- c_p->common.id,DT_UTAG(c_p),ERL_MESSAGE_TERM(msgp));
-#endif
DT_UTAG(c_p) = NIL;
SEQ_TRACE_TOKEN(c_p) = NIL;
}
@@ -1940,12 +1934,6 @@ void process_main(void)
DT_UTAG(c_p) = ERL_MESSAGE_DT_UTAG(msgp);
}
DT_UTAG_FLAGS(c_p) |= DT_UTAG_SPREADING;
-#ifdef DTRACE_TAG_HARDDEBUG
- erts_fprintf(stderr,
- "Dtrace -> (%T) receive tag (%T) "
- "with message %T\r\n",
- c_p->common.id, DT_UTAG(c_p), ERL_MESSAGE_TERM(msgp));
-#endif
} else {
#endif
ASSERT(is_tuple(SEQ_TRACE_TOKEN(c_p)));
@@ -1975,7 +1963,7 @@ void process_main(void)
dtrace_proc_str(c_p, receiver_name);
token2 = SEQ_TRACE_TOKEN(c_p);
- if (token2 != NIL && token2 != am_have_dt_utag) {
+ if (have_seqtrace(token2)) {
tok_label = signed_val(SEQ_TRACE_T_LABEL(token2));
tok_lastcnt = signed_val(SEQ_TRACE_T_LASTCNT(token2));
tok_serial = signed_val(SEQ_TRACE_T_SERIAL(token2));
@@ -1988,11 +1976,21 @@ void process_main(void)
UNLINK_MESSAGE(c_p, msgp);
JOIN_MESSAGE(c_p);
CANCEL_TIMER(c_p);
- free_message(msgp);
+
+ erts_save_message_in_proc(c_p, msgp);
+ c_p->flags &= ~F_DELAY_GC;
+
+ if (ERTS_IS_GC_DESIRED_INTERNAL(c_p, HTOP, E)) {
+ /*
+ * We want to GC soon but we leave a few
+ * reductions giving the message some time
+ * to turn into garbage.
+ */
+ ERTS_VBUMP_LEAVE_REDS_INTERNAL(c_p, 5, FCALLS);
+ }
ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
PROCESS_MAIN_CHK_LOCKS(c_p);
-
NextPF(0, next);
}
@@ -2001,9 +1999,22 @@ void process_main(void)
* message didn't match), then jump to the loop_rec instruction.
*/
OpCase(loop_rec_end_f): {
+
+ ASSERT(c_p->flags & F_DELAY_GC);
+
SET_I((BeamInstr *) Arg(0));
SAVE_MESSAGE(c_p);
- goto loop_rec__;
+ if (FCALLS > 0 || FCALLS > neg_o_reds) {
+ FCALLS--;
+ goto loop_rec__;
+ }
+
+ c_p->flags &= ~F_DELAY_GC;
+ c_p->i = I;
+ SWAPOUT;
+ c_p->arity = 0;
+ c_p->current = NULL;
+ goto do_schedule;
}
/*
* Prepare to wait for a message or a timeout, whichever occurs first.
@@ -2360,9 +2371,9 @@ void process_main(void)
OpCase(new_map_dII): {
Eterm res;
- SWAPOUT;
+ HEAVY_SWAPOUT;
res = new_map(c_p, reg, I-1);
- SWAPIN;
+ HEAVY_SWAPIN;
StoreResult(res, Arg(0));
Next(3+Arg(2));
}
@@ -2450,9 +2461,9 @@ do { \
Eterm map;
GetArg1(1, map);
- SWAPOUT;
+ HEAVY_SWAPOUT;
res = update_map_assoc(c_p, reg, map, I);
- SWAPIN;
+ HEAVY_SWAPIN;
if (is_value(res)) {
StoreResult(res, Arg(2));
Next(5+Arg(4));
@@ -2472,9 +2483,9 @@ do { \
Eterm map;
GetArg1(1, map);
- SWAPOUT;
+ HEAVY_SWAPOUT;
res = update_map_exact(c_p, reg, map, I);
- SWAPIN;
+ HEAVY_SWAPIN;
if (is_value(res)) {
StoreResult(res, Arg(2));
Next(5+Arg(4));
@@ -2733,6 +2744,7 @@ do { \
Eterm (*bf)(Process*, Eterm*, BeamInstr*) = GET_BIF_ADDRESS(Arg(0));
Eterm result;
BeamInstr *next;
+ ErlHeapFragment *live_hf_end;
PRE_BIF_SWAPOUT(c_p);
c_p->fcalls = FCALLS - 1;
@@ -2742,17 +2754,18 @@ do { \
PreFetch(1, next);
ASSERT(!ERTS_PROC_IS_EXITING(c_p));
ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
+ live_hf_end = c_p->mbuf;
result = (*bf)(c_p, reg, I);
ASSERT(!ERTS_PROC_IS_EXITING(c_p) || is_non_value(result));
ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
ERTS_HOLE_CHECK(c_p);
ERTS_SMP_REQ_PROC_MAIN_LOCK(c_p);
- PROCESS_MAIN_CHK_LOCKS(c_p);
- if (c_p->mbuf || MSO(c_p).overhead >= BIN_VHEAP_SZ(c_p)) {
+ if (ERTS_IS_GC_DESIRED(c_p)) {
Uint arity = ((Export *)Arg(0))->code[2];
- result = erts_gc_after_bif_call(c_p, result, reg, arity);
+ result = erts_gc_after_bif_call_lhf(c_p, live_hf_end, result, reg, arity);
E = c_p->stop;
}
+ PROCESS_MAIN_CHK_LOCKS(c_p);
HTOP = HEAP_TOP(c_p);
FCALLS = c_p->fcalls;
if (is_value(result)) {
@@ -2963,6 +2976,9 @@ do { \
}
}
Op1 = small_to_big(ires, tmp_big);
+#ifdef TAG_LITERAL_PTR
+ Op1 |= TAG_LITERAL_PTR;
+#endif
big_shift:
if (i > 0) { /* Left shift. */
@@ -3045,10 +3061,10 @@ do { \
bnot_val = make_small(~signed_val(bnot_val));
} else {
Uint live = Arg(2);
- SWAPOUT;
+ HEAVY_SWAPOUT;
reg[live] = bnot_val;
bnot_val = erts_gc_bnot(c_p, reg, live);
- SWAPIN;
+ HEAVY_SWAPIN;
ERTS_HOLE_CHECK(c_p);
if (is_nil(bnot_val)) {
goto lb_Cl_error;
@@ -3063,9 +3079,9 @@ do { \
OpCase(i_apply): {
BeamInstr *next;
- SWAPOUT;
+ HEAVY_SWAPOUT;
next = apply(c_p, r(0), x(1), x(2), reg);
- SWAPIN;
+ HEAVY_SWAPIN;
if (next != NULL) {
SET_CP(c_p, I+1);
SET_I(next);
@@ -3077,9 +3093,9 @@ do { \
OpCase(i_apply_last_P): {
BeamInstr *next;
- SWAPOUT;
+ HEAVY_SWAPOUT;
next = apply(c_p, r(0), x(1), x(2), reg);
- SWAPIN;
+ HEAVY_SWAPIN;
if (next != NULL) {
SET_CP(c_p, (BeamInstr *) E[0]);
E = ADD_BYTE_OFFSET(E, Arg(0));
@@ -3092,9 +3108,9 @@ do { \
OpCase(i_apply_only): {
BeamInstr *next;
- SWAPOUT;
+ HEAVY_SWAPOUT;
next = apply(c_p, r(0), x(1), x(2), reg);
- SWAPIN;
+ HEAVY_SWAPIN;
if (next != NULL) {
SET_I(next);
Dispatch();
@@ -3106,9 +3122,9 @@ do { \
OpCase(apply_I): {
BeamInstr *next;
- SWAPOUT;
+ HEAVY_SWAPOUT;
next = fixed_apply(c_p, reg, Arg(0));
- SWAPIN;
+ HEAVY_SWAPIN;
if (next != NULL) {
SET_CP(c_p, I+2);
SET_I(next);
@@ -3121,9 +3137,9 @@ do { \
OpCase(apply_last_IP): {
BeamInstr *next;
- SWAPOUT;
+ HEAVY_SWAPOUT;
next = fixed_apply(c_p, reg, Arg(0));
- SWAPIN;
+ HEAVY_SWAPIN;
if (next != NULL) {
SET_CP(c_p, (BeamInstr *) E[0]);
E = ADD_BYTE_OFFSET(E, Arg(1));
@@ -3137,9 +3153,9 @@ do { \
OpCase(i_apply_fun): {
BeamInstr *next;
- SWAPOUT;
+ HEAVY_SWAPOUT;
next = apply_fun(c_p, r(0), x(1), reg);
- SWAPIN;
+ HEAVY_SWAPIN;
if (next != NULL) {
SET_CP(c_p, I+1);
SET_I(next);
@@ -3151,9 +3167,9 @@ do { \
OpCase(i_apply_fun_last_P): {
BeamInstr *next;
- SWAPOUT;
+ HEAVY_SWAPOUT;
next = apply_fun(c_p, r(0), x(1), reg);
- SWAPIN;
+ HEAVY_SWAPIN;
if (next != NULL) {
SET_CP(c_p, (BeamInstr *) E[0]);
E = ADD_BYTE_OFFSET(E, Arg(0));
@@ -3166,9 +3182,9 @@ do { \
OpCase(i_apply_fun_only): {
BeamInstr *next;
- SWAPOUT;
+ HEAVY_SWAPOUT;
next = apply_fun(c_p, r(0), x(1), reg);
- SWAPIN;
+ HEAVY_SWAPIN;
if (next != NULL) {
SET_I(next);
Dispatchfun();
@@ -3179,9 +3195,9 @@ do { \
OpCase(i_call_fun_I): {
BeamInstr *next;
- SWAPOUT;
+ HEAVY_SWAPOUT;
next = call_fun(c_p, Arg(0), reg, THE_NON_VALUE);
- SWAPIN;
+ HEAVY_SWAPIN;
if (next != NULL) {
SET_CP(c_p, I+2);
SET_I(next);
@@ -3193,9 +3209,9 @@ do { \
OpCase(i_call_fun_last_IP): {
BeamInstr *next;
- SWAPOUT;
+ HEAVY_SWAPOUT;
next = call_fun(c_p, Arg(0), reg, THE_NON_VALUE);
- SWAPIN;
+ HEAVY_SWAPIN;
if (next != NULL) {
SET_CP(c_p, (BeamInstr *) E[0]);
E = ADD_BYTE_OFFSET(E, Arg(1));
@@ -3394,9 +3410,9 @@ do { \
* code[3]: &&call_error_handler
* code[4]: Not used
*/
- SWAPOUT;
+ HEAVY_SWAPOUT;
I = call_error_handler(c_p, I-3, reg, am_undefined_function);
- SWAPIN;
+ HEAVY_SWAPIN;
if (I) {
Goto(*I);
}
@@ -3411,9 +3427,6 @@ do { \
goto do_schedule;
} else {
ASSERT(!is_value(r(0)));
- if (c_p->mbuf) {
- erts_garbage_collect(c_p, 0, reg+1, 3);
- }
SWAPIN;
Goto(*I);
}
@@ -3437,6 +3450,7 @@ do { \
* I[3]: Function pointer to dirty NIF
*/
BifFunction vbf;
+ ErlHeapFragment *live_hf_end;
DTRACE_NIF_ENTRY(c_p, (Eterm)I[-3], (Eterm)I[-2], (Uint)I[-1]);
c_p->current = I-3; /* current and vbf set to please handle_error */
@@ -3452,6 +3466,7 @@ do { \
NifF* fp = vbf = (NifF*) I[1];
struct enif_environment_t env;
erts_pre_nif(&env, c_p, (struct erl_module_nif*)I[2]);
+ live_hf_end = c_p->mbuf;
nif_bif_result = (*fp)(&env, bif_nif_arity, reg);
if (env.exception_thrown)
nif_bif_result = THE_NON_VALUE;
@@ -3494,6 +3509,7 @@ do { \
{
Eterm (*bf)(Process*, Eterm*, BeamInstr*) = vbf;
ASSERT(!ERTS_PROC_IS_EXITING(c_p));
+ live_hf_end = c_p->mbuf;
nif_bif_result = (*bf)(c_p, reg, I);
ASSERT(!ERTS_PROC_IS_EXITING(c_p) ||
is_non_value(nif_bif_result));
@@ -3506,9 +3522,10 @@ do { \
apply_bif_or_nif_epilogue:
ERTS_SMP_REQ_PROC_MAIN_LOCK(c_p);
ERTS_HOLE_CHECK(c_p);
- if (c_p->mbuf) {
- nif_bif_result = erts_gc_after_bif_call(c_p, nif_bif_result,
- reg, bif_nif_arity);
+ if (ERTS_IS_GC_DESIRED(c_p)) {
+ nif_bif_result = erts_gc_after_bif_call_lhf(c_p, live_hf_end,
+ nif_bif_result,
+ reg, bif_nif_arity);
}
SWAPIN; /* There might have been a garbage collection. */
FCALLS = c_p->fcalls;
@@ -3541,6 +3558,16 @@ do { \
StoreBifResult(1, result);
}
+ OpCase(i_get_hash_cId):
+ {
+ Eterm arg;
+ Eterm result;
+
+ GetArg1(0, arg);
+ result = erts_pd_hash_get_with_hx(c_p, Arg(1), arg);
+ StoreBifResult(2, result);
+ }
+
{
Eterm case_end_val;
@@ -3949,10 +3976,10 @@ do { \
Eterm Size;
GetArg1(4, Size);
- SWAPOUT;
+ HEAVY_SWAPOUT;
reg[live] = x(SCRATCH_X_REG);
res = erts_bs_append(c_p, reg, live, Size, Arg(1), Arg(3));
- SWAPIN;
+ HEAVY_SWAPIN;
if (is_non_value(res)) {
/* c_p->freason is already set (may be either BADARG or SYSTEM_LIMIT). */
goto lb_Cl_error;
@@ -3977,9 +4004,9 @@ do { \
}
OpCase(bs_init_writable): {
- SWAPOUT;
+ HEAVY_SWAPOUT;
r(0) = erts_bs_init_writable(c_p, r(0));
- SWAPIN;
+ HEAVY_SWAPIN;
Next(0);
}
@@ -4807,7 +4834,7 @@ do { \
BeamInstr *next;
next = call_fun(c_p, c_p->arity - 1, reg, THE_NON_VALUE);
- SWAPIN;
+ HEAVY_SWAPIN;
if (next != NULL) {
SET_I(next);
Dispatchfun();
@@ -4856,20 +4883,22 @@ do { \
}
OpCase(i_hibernate): {
- SWAPOUT;
+ HEAVY_SWAPOUT;
if (erts_hibernate(c_p, r(0), x(1), x(2), reg)) {
+ FCALLS = c_p->fcalls;
c_p->flags &= ~F_HIBERNATE_SCHED;
goto do_schedule;
} else {
+ HEAVY_SWAPIN;
I = handle_error(c_p, I, reg, hibernate_3);
goto post_error_handling;
}
}
OpCase(i_debug_breakpoint): {
- SWAPOUT;
+ HEAVY_SWAPOUT;
I = call_error_handler(c_p, I-3, reg, am_breakpoint);
- SWAPIN;
+ HEAVY_SWAPIN;
if (I) {
Goto(*I);
}
@@ -6080,7 +6109,7 @@ call_fun(Process* p, /* Current process. */
*/
module = fe->module;
if ((modp = erts_get_module(module, code_ix)) != NULL
- && modp->curr.code != NULL) {
+ && modp->curr.code_hdr != NULL) {
/*
* There is a module loaded, but obviously the fun is not
* defined in it. We must not call the error_handler
@@ -6337,13 +6366,6 @@ new_map(Process* p, Eterm* reg, BeamInstr* I)
erts_factory_proc_init(&factory, p);
res = erts_hashmap_from_array(&factory, thp, n/2, 0);
erts_factory_close(&factory);
- if (p->mbuf) {
- Uint live = Arg(2);
- reg[live] = res;
- erts_garbage_collect(p, 0, reg, live+1);
- res = reg[live];
- E = p->stop;
- }
return res;
}
@@ -6409,13 +6431,6 @@ update_map_assoc(Process* p, Eterm* reg, Eterm map, BeamInstr* I)
hx = hashmap_make_hash(new_key);
res = erts_hashmap_insert(p, hx, new_key, val, res, 0);
- if (p->mbuf) {
- Uint live = Arg(3);
- reg[live] = res;
- erts_garbage_collect(p, 0, reg, live+1);
- res = reg[live];
- E = p->stop;
- }
new_p += 2;
}
@@ -6575,12 +6590,6 @@ update_map_assoc(Process* p, Eterm* reg, Eterm map, BeamInstr* I)
/* The expensive case, need to build a hashmap */
if (n > MAP_SMALL_MAP_LIMIT) {
res = erts_hashmap_from_ks_and_vs(p,flatmap_get_keys(mp),flatmap_get_values(mp),n);
- if (p->mbuf) {
- Uint live = Arg(3);
- reg[live] = res;
- erts_garbage_collect(p, 0, reg, live+1);
- res = reg[live];
- }
}
return res;
}
@@ -6636,14 +6645,6 @@ update_map_exact(Process* p, Eterm* reg, Eterm map, BeamInstr* I)
return res;
}
- if (p->mbuf) {
- Uint live = Arg(3);
- reg[live] = res;
- erts_garbage_collect(p, 0, reg, live+1);
- res = reg[live];
- E = p->stop;
- }
-
new_p += 2;
}
return res;
diff --git a/erts/emulator/beam/beam_load.c b/erts/emulator/beam/beam_load.c
index a9d47eb7b0..d367cce212 100644
--- a/erts/emulator/beam/beam_load.c
+++ b/erts/emulator/beam/beam_load.c
@@ -80,7 +80,7 @@ ErlDrvBinary* erts_gzinflate_buffer(char*, int);
typedef struct {
Uint value; /* Value of label (NULL if not known yet). */
- Uint patches; /* Index (into code buffer) to first location
+ Sint patches; /* Index (into code buffer) to first location
* which must be patched with the value of this label.
*/
#ifdef ERTS_SMP
@@ -284,9 +284,10 @@ typedef struct LoaderState {
int specific_op; /* Specific opcode (-1 if not found). */
int num_functions; /* Number of functions in module. */
int num_labels; /* Number of labels. */
- int code_buffer_size; /* Size of code buffer in words. */
- BeamInstr* code; /* Loaded code. */
- int ci; /* Current index into loaded code. */
+ BeamCodeHeader* hdr; /* Loaded code header */
+ BeamInstr* codev; /* Loaded code buffer */
+ int codev_size; /* Size of code buffer in words. */
+ int ci; /* Current index into loaded code buffer. */
Label* labels;
StringPatch* string_patches; /* Linked list of position into string table to patch. */
BeamInstr catches; /* Linked list of catch_yf instructions. */
@@ -480,7 +481,7 @@ static void free_literal_fragment(ErlHeapFragment*);
static void loader_state_dtor(Binary* magic);
static Eterm insert_new_code(Process *c_p, ErtsProcLocks c_p_locks,
Eterm group_leader, Eterm module,
- BeamInstr* code, Uint size);
+ BeamCodeHeader* code, Uint size);
static int init_iff_file(LoaderState* stp, byte* code, Uint size);
static int scan_iff_file(LoaderState* stp, Uint* chunk_types,
Uint num_types, Uint num_mandatory);
@@ -526,15 +527,15 @@ static void new_string_patch(LoaderState* stp, int pos);
static Uint new_literal(LoaderState* stp, Eterm** hpp, Uint heap_size);
static int genopargcompare(GenOpArg* a, GenOpArg* b);
static Eterm get_module_info(Process* p, ErtsCodeIndex code_ix,
- BeamInstr* code, Eterm module, Eterm what);
+ BeamCodeHeader*, Eterm module, Eterm what);
static Eterm exported_from_module(Process* p, ErtsCodeIndex code_ix,
Eterm mod);
-static Eterm functions_in_module(Process* p, BeamInstr* code);
-static Eterm attributes_for_module(Process* p, BeamInstr* code);
-static Eterm compilation_info_for_module(Process* p, BeamInstr* code);
-static Eterm md5_of_module(Process* p, BeamInstr* code);
-static Eterm has_native(BeamInstr* code);
-static Eterm native_addresses(Process* p, BeamInstr* code);
+static Eterm functions_in_module(Process* p, BeamCodeHeader*);
+static Eterm attributes_for_module(Process* p, BeamCodeHeader*);
+static Eterm compilation_info_for_module(Process* p, BeamCodeHeader*);
+static Eterm md5_of_module(Process* p, BeamCodeHeader*);
+static Eterm has_native(BeamCodeHeader*);
+static Eterm native_addresses(Process* p, BeamCodeHeader*);
int patch_funentries(Eterm Patchlist);
int patch(Eterm Addresses, Uint fe);
static int safe_mul(UWord a, UWord b, UWord* resp);
@@ -601,6 +602,7 @@ extern void check_allocated_block(Uint type, void *blk);
#define CHKBLK(TYPE,BLK) /* nothing */
#endif
+
Eterm
erts_prepare_loading(Binary* magic, Process *c_p, Eterm group_leader,
Eterm* modp, byte* code, Uint unloaded_size)
@@ -641,20 +643,27 @@ erts_prepare_loading(Binary* magic, Process *c_p, Eterm group_leader,
/*
* Initialize code area.
*/
- stp->code_buffer_size = 2048 + stp->num_functions;
- stp->code = (BeamInstr *) erts_alloc(ERTS_ALC_T_CODE,
- sizeof(BeamInstr) * stp->code_buffer_size);
+ stp->codev_size = 2048 + stp->num_functions;
+ stp->hdr = (BeamCodeHeader*) erts_alloc(ERTS_ALC_T_CODE,
+ (offsetof(BeamCodeHeader,functions)
+ + sizeof(BeamInstr) * stp->codev_size));
- stp->code[MI_NUM_FUNCTIONS] = stp->num_functions;
- stp->ci = MI_FUNCTIONS + stp->num_functions + 1;
+ stp->hdr->num_functions = stp->num_functions;
- stp->code[MI_ATTR_PTR] = 0;
- stp->code[MI_ATTR_SIZE] = 0;
- stp->code[MI_ATTR_SIZE_ON_HEAP] = 0;
- stp->code[MI_COMPILE_PTR] = 0;
- stp->code[MI_COMPILE_SIZE] = 0;
- stp->code[MI_COMPILE_SIZE_ON_HEAP] = 0;
- stp->code[MI_MD5_PTR] = 0;
+ /* Let the codev array start at functions[0] in order to index
+ * both function pointers and the loaded code itself that follows.
+ */
+ stp->codev = (BeamInstr*) &stp->hdr->functions;
+ stp->ci = stp->num_functions + 1;
+
+ stp->hdr->attr_ptr = NULL;
+ stp->hdr->attr_size = 0;
+ stp->hdr->attr_size_on_heap = 0;
+ stp->hdr->compile_ptr = NULL;
+ stp->hdr->compile_size = 0;
+ stp->hdr->compile_size_on_heap = 0;
+ stp->hdr->literals_start = NULL;
+ stp->hdr->md5_ptr = NULL;
/*
* Read the atom table.
@@ -776,7 +785,7 @@ erts_finish_loading(Binary* magic, Process* c_p,
CHKBLK(ERTS_ALC_T_CODE,stp->code);
retval = insert_new_code(c_p, c_p_locks, stp->group_leader, stp->module,
- stp->code, stp->loaded_size);
+ stp->hdr, stp->loaded_size);
if (retval != NIL) {
goto load_error;
}
@@ -799,7 +808,8 @@ erts_finish_loading(Binary* magic, Process* c_p,
debug_dump_code(stp->code,stp->ci);
#endif
#endif
- stp->code = NULL; /* Prevent code from being freed. */
+ stp->hdr = NULL; /* Prevent code from being freed. */
+ stp->codev = NULL;
*modp = stp->module;
/*
@@ -831,7 +841,8 @@ erts_alloc_loader_state(void)
stp->specific_op = -1;
stp->genop = NULL;
stp->atom = NULL;
- stp->code = NULL;
+ stp->hdr = NULL;
+ stp->codev = NULL;
stp->labels = NULL;
stp->import = NULL;
stp->export = NULL;
@@ -870,7 +881,7 @@ erts_module_for_prepared_code(Binary* magic)
return NIL;
}
stp = ERTS_MAGIC_BIN_DATA(magic);
- if (stp->code != 0) {
+ if (stp->hdr != 0) {
return stp->module;
} else {
return NIL;
@@ -891,7 +902,7 @@ static ErlHeapFragment* new_literal_fragment(Uint size)
ErlHeapFragment* bp;
bp = (ErlHeapFragment*) ERTS_HEAP_ALLOC(ERTS_ALC_T_PREPARED_CODE,
ERTS_HEAP_FRAG_SIZE(size));
- ERTS_INIT_HEAP_FRAG(bp, size);
+ ERTS_INIT_HEAP_FRAG(bp, size, size);
return bp;
}
@@ -920,9 +931,13 @@ loader_state_dtor(Binary* magic)
driver_free_binary(stp->bin);
stp->bin = 0;
}
- if (stp->code != 0) {
- erts_free(ERTS_ALC_T_CODE, stp->code);
- stp->code = 0;
+ if (stp->hdr != 0) {
+ if (stp->hdr->literals_start) {
+ erts_free(ERTS_ALC_T_LITERAL, stp->hdr->literals_start);
+ }
+ erts_free(ERTS_ALC_T_CODE, stp->hdr);
+ stp->hdr = 0;
+ stp->codev = 0;
}
if (stp->labels != 0) {
erts_free(ERTS_ALC_T_PREPARED_CODE, (void *) stp->labels);
@@ -995,7 +1010,7 @@ loader_state_dtor(Binary* magic)
static Eterm
insert_new_code(Process *c_p, ErtsProcLocks c_p_locks,
- Eterm group_leader, Eterm module, BeamInstr* code,
+ Eterm group_leader, Eterm module, BeamCodeHeader* code_hdr,
Uint size)
{
Module* modp;
@@ -1016,7 +1031,7 @@ insert_new_code(Process *c_p, ErtsProcLocks c_p_locks,
erts_total_code_size += size;
modp = erts_put_module(module);
- modp->curr.code = code;
+ modp->curr.code_hdr = code_hdr;
modp->curr.code_length = size;
modp->curr.catches = BEAM_CATCHES_NIL; /* Will be filled in later. */
@@ -1024,7 +1039,7 @@ insert_new_code(Process *c_p, ErtsProcLocks c_p_locks,
* Update ranges (used for finding a function from a PC value).
*/
- erts_update_ranges(code, size);
+ erts_update_ranges((BeamInstr*)modp->curr.code_hdr, size);
return NIL;
}
@@ -1373,7 +1388,7 @@ read_export_table(LoaderState* stp)
if (value == 0) {
LoadError2(stp, "export table entry %d: label %d not resolved", i, n);
}
- stp->export[i].address = address = stp->code + value;
+ stp->export[i].address = address = stp->codev + value;
/*
* Find out if there is a BIF with the same name.
@@ -1392,7 +1407,7 @@ read_export_table(LoaderState* stp)
* any other functions that walk through all local functions.
*/
- if (stp->labels[n].patches) {
+ if (stp->labels[n].patches >= 0) {
LoadError3(stp, "there are local calls to the stub for "
"the BIF %T:%T/%d",
stp->module, func, arity);
@@ -1513,8 +1528,8 @@ read_literal_table(LoaderState* stp)
}
if (heap_size > 0) {
- erts_factory_message_init(&factory, NULL, NULL,
- new_literal_fragment(heap_size));
+ erts_factory_heap_frag_init(&factory,
+ new_literal_fragment(heap_size));
factory.alloc_type = ERTS_ALC_T_PREPARED_CODE;
val = erts_decode_ext(&factory, &p);
@@ -1735,7 +1750,7 @@ read_code_header(LoaderState* stp)
stp->num_labels * sizeof(Label));
for (i = 0; i < stp->num_labels; i++) {
stp->labels[i].value = 0;
- stp->labels[i].patches = 0;
+ stp->labels[i].patches = -1;
#ifdef ERTS_SMP
stp->labels[i].looprec_targeted = 0;
#endif
@@ -1754,13 +1769,14 @@ read_code_header(LoaderState* stp)
} else {}
#define CodeNeed(w) do { \
- ASSERT(ci <= code_buffer_size); \
- if (code_buffer_size < ci+(w)) { \
- code_buffer_size = 2*ci+(w); \
- stp->code = code = \
- (BeamInstr *) erts_realloc(ERTS_ALC_T_CODE, \
- (void *) code, \
- code_buffer_size * sizeof(BeamInstr)); \
+ ASSERT(ci <= codev_size); \
+ if (codev_size < ci+(w)) { \
+ codev_size = 2*ci+(w); \
+ stp->hdr = (BeamCodeHeader*) erts_realloc(ERTS_ALC_T_CODE, \
+ (void *) stp->hdr, \
+ (offsetof(BeamCodeHeader,functions) \
+ + codev_size * sizeof(BeamInstr))); \
+ code = stp->codev = (BeamInstr*) &stp->hdr->functions; \
} \
} while (0)
@@ -1776,7 +1792,7 @@ load_code(LoaderState* stp)
int arg; /* Number of current argument. */
int num_specific; /* Number of specific ops for current. */
BeamInstr* code;
- int code_buffer_size;
+ int codev_size;
int specific;
Uint last_label = 0; /* Number of last label. */
Uint function_number = 0;
@@ -1793,15 +1809,15 @@ load_code(LoaderState* stp)
FUNC_INFO_SZ = 5
};
- code = stp->code;
- code_buffer_size = stp->code_buffer_size;
+ code = stp->codev;
+ codev_size = stp->codev_size;
ci = stp->ci;
for (;;) {
int new_op;
GenOp* tmp_op;
- ASSERT(ci <= code_buffer_size);
+ ASSERT(ci <= codev_size);
get_next_instr:
GetByte(stp, new_op);
@@ -2416,8 +2432,7 @@ load_code(LoaderState* stp)
switch (stp->specific_op) {
case op_i_func_info_IaaI:
{
- Uint offset;
-
+ Sint offset;
if (function_number >= stp->num_functions) {
LoadError1(stp, "too many functions in module (header said %d)",
stp->num_functions);
@@ -2459,15 +2474,15 @@ load_code(LoaderState* stp)
stp->arity = code[ci-1];
ASSERT(stp->labels[last_label].value == ci - FUNC_INFO_SZ);
- offset = MI_FUNCTIONS + function_number;
- code[offset] = stp->labels[last_label].patches;
+ stp->hdr->functions[function_number] = (BeamInstr*) stp->labels[last_label].patches;
+ offset = function_number;
stp->labels[last_label].patches = offset;
function_number++;
if (stp->arity > MAX_ARG) {
LoadError1(stp, "too many arguments: %d", stp->arity);
}
#ifdef DEBUG
- ASSERT(stp->labels[0].patches == 0); /* Should not be referenced. */
+ ASSERT(stp->labels[0].patches < 0); /* Should not be referenced. */
for (i = 1; i < stp->num_labels; i++) {
ASSERT(stp->labels[i].patches < ci);
}
@@ -2537,7 +2552,7 @@ load_code(LoaderState* stp)
* End of code found.
*/
case op_int_code_end:
- stp->code_buffer_size = code_buffer_size;
+ stp->codev_size = codev_size;
stp->ci = ci;
stp->function = THE_NON_VALUE;
stp->genop = NULL;
@@ -4269,6 +4284,53 @@ gen_get_map_element(LoaderState* stp, GenOpArg Fail, GenOpArg Src,
return op;
}
+static int
+hash_internal_genop_arg(LoaderState* stp, GenOpArg Key, Uint32* hx)
+{
+ switch (Key.type) {
+ case TAG_a:
+ *hx = atom_tab(atom_val(Key.val))->slot.bucket.hvalue;
+ return 1;
+ case TAG_i:
+ *hx = Key.val;
+ return 1;
+ case TAG_n:
+ *hx = make_internal_hash(NIL);
+ return 1;
+ case TAG_q:
+ *hx = make_internal_hash(stp->literals[Key.val].term);
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+
+static GenOp*
+gen_get(LoaderState* stp, GenOpArg Src, GenOpArg Dst)
+{
+ GenOp* op;
+ Uint32 hx = 0;
+
+ NEW_GENOP(stp, op);
+ op->next = NULL;
+ if (hash_internal_genop_arg(stp, Src, &hx)) {
+ op->arity = 3;
+ op->op = genop_i_get_hash_3;
+ op->a[0] = Src;
+ op->a[1].type = TAG_u;
+ op->a[1].val = (BeamInstr) hx;
+ op->a[2] = Dst;
+ } else {
+ op->arity = 2;
+ op->op = genop_i_get_2;
+ op->a[0] = Src;
+ op->a[1] = Dst;
+ }
+ return op;
+}
+
+
static GenOp*
gen_get_map_elements(LoaderState* stp, GenOpArg Fail, GenOpArg Src,
GenOpArg Size, GenOpArg* Rest)
@@ -4347,8 +4409,8 @@ gen_has_map_fields(LoaderState* stp, GenOpArg Fail, GenOpArg Src,
static int
freeze_code(LoaderState* stp)
{
- BeamInstr* code = stp->code;
- Uint *literal_end = NULL;
+ BeamCodeHeader* code_hdr = stp->hdr;
+ BeamInstr* codev = (BeamInstr*) &stp->hdr->functions;
int i;
byte* str_table;
unsigned strtab_size = stp->chunks[STR_CHUNK].size;
@@ -4373,77 +4435,76 @@ freeze_code(LoaderState* stp)
if (stp->line_instr == 0) {
line_size = 0;
} else {
- line_size = (MI_LINE_FUNC_TAB + (stp->num_functions + 1) +
- (stp->current_li+1) + stp->num_fnames) *
- sizeof(Eterm) + (stp->current_li+1) * stp->loc_size;
+ line_size = (offsetof(BeamCodeLineTab,func_tab)
+ + (stp->num_functions + 1) * sizeof(BeamInstr**) /* func_tab */
+ + (stp->current_li + 1) * sizeof(BeamInstr*) /* line items */
+ + stp->num_fnames * sizeof(Eterm) /* fname table */
+ + (stp->current_li + 1) * stp->loc_size); /* loc_tab */
}
- size = (stp->ci * sizeof(BeamInstr)) +
- (stp->total_literal_size * sizeof(Eterm)) +
+ size = offsetof(BeamCodeHeader,functions) + (stp->ci * sizeof(BeamInstr)) +
strtab_size + attr_size + compile_size + MD5_SIZE + line_size;
/*
* Move the code to its final location.
*/
- code = (BeamInstr *) erts_realloc(ERTS_ALC_T_CODE, (void *) code, size);
- CHKBLK(ERTS_ALC_T_CODE,code);
+ code_hdr = (BeamCodeHeader*) erts_realloc(ERTS_ALC_T_CODE, (void *) code_hdr, size);
+ codev = (BeamInstr*) &code_hdr->functions;
+ CHKBLK(ERTS_ALC_T_CODE,code_hdr);
/*
* Place a pointer to the op_int_code_end instruction in the
* function table in the beginning of the file.
*/
- code[MI_FUNCTIONS+stp->num_functions] = (BeamInstr) (code + stp->ci - 1);
- CHKBLK(ERTS_ALC_T_CODE,code);
+ code_hdr->functions[stp->num_functions] = (codev + stp->ci - 1);
+ CHKBLK(ERTS_ALC_T_CODE,code_hdr);
/*
* Store the pointer to the on_load function.
*/
if (stp->on_load) {
- code[MI_ON_LOAD_FUNCTION_PTR] = (BeamInstr) (code + stp->on_load);
+ code_hdr->on_load_function_ptr = codev + stp->on_load;
} else {
- code[MI_ON_LOAD_FUNCTION_PTR] = 0;
+ code_hdr->on_load_function_ptr = NULL;
}
- CHKBLK(ERTS_ALC_T_CODE,code);
+ CHKBLK(ERTS_ALC_T_CODE,code_hdr);
- literal_end = (Uint *) (code+stp->ci);
/*
- * Place the literal heap directly after the code and fix up all
- * instructions that refer to it.
+ * Place the literals in their own allocated heap (for fast range check)
+ * and fix up all instructions that refer to it.
*/
{
- Uint* ptr;
- Uint* low;
- Uint* high;
+ Eterm* ptr;
LiteralPatch* lp;
ErlOffHeap code_off_heap;
ERTS_INIT_OFF_HEAP(&code_off_heap);
- low = (Uint *) (code+stp->ci);
- high = low + stp->total_literal_size;
- code[MI_LITERALS_START] = (BeamInstr) low;
- code[MI_LITERALS_END] = (BeamInstr) high;
- ptr = low;
+ ptr = (Eterm*)erts_alloc(ERTS_ALC_T_LITERAL,
+ stp->total_literal_size*sizeof(Eterm));
+ code_hdr->literals_start = ptr;
+ code_hdr->literals_end = ptr + stp->total_literal_size;
for (i = 0; i < stp->num_literals; i++) {
- if (stp->literals[i].heap_frags) {
- move_multi_frags(&ptr, &code_off_heap, stp->literals[i].heap_frags,
- &stp->literals[i].term, 1);
+ if (is_not_immed(stp->literals[i].term)) {
+ erts_move_multi_frags(&ptr, &code_off_heap,
+ stp->literals[i].heap_frags,
+ &stp->literals[i].term, 1, 1);
+ ASSERT(erts_is_literal(stp->literals[i].term,
+ ptr_val(stp->literals[i].term)));
}
- else ASSERT(is_immed(stp->literals[i].term));
}
- code[MI_LITERALS_OFF_HEAP] = (BeamInstr) code_off_heap.first;
+ code_hdr->literals_off_heap = code_off_heap.first;
lp = stp->literal_patches;
while (lp != 0) {
BeamInstr* op_ptr;
Literal* lit;
- op_ptr = code + lp->pos;
+ op_ptr = codev + lp->pos;
lit = &stp->literals[op_ptr[0]];
op_ptr[0] = lit->term;
lp = lp->next;
}
- literal_end += stp->total_literal_size;
}
CHKBLK(ERTS_ALC_T_CODE,code);
@@ -4451,52 +4512,49 @@ freeze_code(LoaderState* stp)
* If there is line information, place it here.
*/
if (stp->line_instr == 0) {
- code[MI_LINE_TABLE] = (BeamInstr) 0;
- str_table = (byte *) literal_end;
+ code_hdr->line_table = NULL;
+ str_table = (byte *) (codev + stp->ci);
} else {
- Eterm* line_tab = (Eterm *) literal_end;
- Eterm* p;
- int ftab_size = stp->num_functions;
- int num_instrs = stp->current_li;
- Eterm* first_line_item;
+ BeamCodeLineTab* const line_tab = (BeamCodeLineTab *) (codev+stp->ci);
+ const int ftab_size = stp->num_functions;
+ const int num_instrs = stp->current_li;
+ const BeamInstr** const line_items =
+ (const BeamInstr**) &line_tab->func_tab[ftab_size + 1];
- code[MI_LINE_TABLE] = (BeamInstr) line_tab;
- p = line_tab + MI_LINE_FUNC_TAB;
+ code_hdr->line_table = line_tab;
- first_line_item = (p + ftab_size + 1);
for (i = 0; i < ftab_size; i++) {
- *p++ = (Eterm) (BeamInstr) (first_line_item + stp->func_line[i]);
+ line_tab->func_tab[i] = line_items + stp->func_line[i];
}
- *p++ = (Eterm) (BeamInstr) (first_line_item + num_instrs);
- ASSERT(p == first_line_item);
+ line_tab->func_tab[i] = line_items + num_instrs;
+
for (i = 0; i < num_instrs; i++) {
- *p++ = (Eterm) (BeamInstr) (code + stp->line_instr[i].pos);
+ line_items[i] = codev + stp->line_instr[i].pos;
}
- *p++ = (Eterm) (BeamInstr) (code + stp->ci - 1);
+ line_items[i] = codev + stp->ci - 1;
- line_tab[MI_LINE_FNAME_PTR] = (Eterm) (BeamInstr) p;
- memcpy(p, stp->fname, stp->num_fnames*sizeof(Eterm));
- p += stp->num_fnames;
+ line_tab->fname_ptr = (Eterm*) &line_items[i + 1];
+ memcpy(line_tab->fname_ptr, stp->fname, stp->num_fnames*sizeof(Eterm));
- line_tab[MI_LINE_LOC_TAB] = (Eterm) (BeamInstr) p;
- line_tab[MI_LINE_LOC_SIZE] = stp->loc_size;
+ line_tab->loc_size = stp->loc_size;
if (stp->loc_size == 2) {
- Uint16* locp = (Uint16 *) p;
- for (i = 0; i < num_instrs; i++) {
+ Uint16* locp = (Uint16 *) &line_tab->fname_ptr[stp->num_fnames];
+ line_tab->loc_tab.p2 = locp;
+ for (i = 0; i < num_instrs; i++) {
*locp++ = (Uint16) stp->line_instr[i].loc;
- }
- *locp++ = LINE_INVALID_LOCATION;
- str_table = (byte *) locp;
+ }
+ *locp++ = LINE_INVALID_LOCATION;
+ str_table = (byte *) locp;
} else {
- Uint32* locp = (Uint32 *) p;
- ASSERT(stp->loc_size == 4);
+ Uint32* locp = (Uint32 *) &line_tab->fname_ptr[stp->num_fnames];
+ ASSERT(stp->loc_size == 4);
+ line_tab->loc_tab.p4 = locp;
for (i = 0; i < num_instrs; i++) {
*locp++ = stp->line_instr[i].loc;
}
*locp++ = LINE_INVALID_LOCATION;
- str_table = (byte *) locp;
+ str_table = (byte *) locp;
}
-
CHKBLK(ERTS_ALC_T_CODE,code);
}
@@ -4508,13 +4566,13 @@ freeze_code(LoaderState* stp)
if (attr_size) {
byte* attr = str_table + strtab_size;
sys_memcpy(attr, stp->chunks[ATTR_CHUNK].start, stp->chunks[ATTR_CHUNK].size);
- code[MI_ATTR_PTR] = (BeamInstr) attr;
- code[MI_ATTR_SIZE] = (BeamInstr) stp->chunks[ATTR_CHUNK].size;
+ code_hdr->attr_ptr = attr;
+ code_hdr->attr_size = (BeamInstr) stp->chunks[ATTR_CHUNK].size;
decoded_size = erts_decode_ext_size(attr, attr_size);
if (decoded_size < 0) {
LoadError0(stp, "bad external term representation of module attributes");
}
- code[MI_ATTR_SIZE_ON_HEAP] = decoded_size;
+ code_hdr->attr_size_on_heap = decoded_size;
}
CHKBLK(ERTS_ALC_T_CODE,code);
if (compile_size) {
@@ -4524,9 +4582,9 @@ freeze_code(LoaderState* stp)
stp->chunks[COMPILE_CHUNK].size);
CHKBLK(ERTS_ALC_T_CODE,code);
- code[MI_COMPILE_PTR] = (BeamInstr) compile_info;
+ code_hdr->compile_ptr = compile_info;
CHKBLK(ERTS_ALC_T_CODE,code);
- code[MI_COMPILE_SIZE] = (BeamInstr) stp->chunks[COMPILE_CHUNK].size;
+ code_hdr->compile_size = (BeamInstr) stp->chunks[COMPILE_CHUNK].size;
CHKBLK(ERTS_ALC_T_CODE,code);
decoded_size = erts_decode_ext_size(compile_info, compile_size);
CHKBLK(ERTS_ALC_T_CODE,code);
@@ -4534,7 +4592,7 @@ freeze_code(LoaderState* stp)
LoadError0(stp, "bad external term representation of compilation information");
}
CHKBLK(ERTS_ALC_T_CODE,code);
- code[MI_COMPILE_SIZE_ON_HEAP] = decoded_size;
+ code_hdr->compile_size_on_heap = decoded_size;
}
CHKBLK(ERTS_ALC_T_CODE,code);
{
@@ -4542,7 +4600,7 @@ freeze_code(LoaderState* stp)
CHKBLK(ERTS_ALC_T_CODE,code);
sys_memcpy(md5_sum, stp->mod_md5, MD5_SIZE);
CHKBLK(ERTS_ALC_T_CODE,code);
- code[MI_MD5_PTR] = (BeamInstr) md5_sum;
+ code_hdr->md5_ptr = md5_sum;
CHKBLK(ERTS_ALC_T_CODE,code);
}
CHKBLK(ERTS_ALC_T_CODE,code);
@@ -4551,7 +4609,7 @@ freeze_code(LoaderState* stp)
* Make sure that we have not overflowed the allocated code space.
*/
ASSERT(str_table + strtab_size + attr_size + compile_size + MD5_SIZE ==
- ((byte *) code) + size);
+ ((byte *) code_hdr) + size);
/*
* Patch all instructions that refer to the string table.
@@ -4563,46 +4621,47 @@ freeze_code(LoaderState* stp)
BeamInstr* op_ptr;
byte* strp;
- op_ptr = code + sp->pos;
+ op_ptr = codev + sp->pos;
strp = str_table + op_ptr[0];
op_ptr[0] = (BeamInstr) strp;
sp = sp->next;
}
}
- CHKBLK(ERTS_ALC_T_CODE,code);
+ CHKBLK(ERTS_ALC_T_CODE,code_hdr);
/*
* Resolve all labels.
*/
for (i = 0; i < stp->num_labels; i++) {
- Uint this_patch;
- Uint next_patch;
+ Sint this_patch;
+ Sint next_patch;
Uint value = stp->labels[i].value;
- if (value == 0 && stp->labels[i].patches != 0) {
+ if (value == 0 && stp->labels[i].patches >= 0) {
LoadError1(stp, "label %d not resolved", i);
}
ASSERT(value < stp->ci);
this_patch = stp->labels[i].patches;
- while (this_patch != 0) {
+ while (this_patch >= 0) {
ASSERT(this_patch < stp->ci);
- next_patch = code[this_patch];
+ next_patch = codev[this_patch];
ASSERT(next_patch < stp->ci);
- code[this_patch] = (BeamInstr) (code + value);
+ codev[this_patch] = (BeamInstr) (codev + value);
this_patch = next_patch;
}
}
- CHKBLK(ERTS_ALC_T_CODE,code);
+ CHKBLK(ERTS_ALC_T_CODE,code_hdr);
/*
* Save the updated code pointer and code size.
*/
- stp->code = code;
+ stp->hdr = code_hdr;
+ stp->codev = codev;
stp->loaded_size = size;
- CHKBLK(ERTS_ALC_T_CODE,code);
+ CHKBLK(ERTS_ALC_T_CODE,code_hdr);
return 1;
load_error:
@@ -4610,7 +4669,8 @@ freeze_code(LoaderState* stp)
* Make sure that the caller frees the newly reallocated block, and
* not the old one (in case it has moved).
*/
- stp->code = code;
+ stp->hdr = code_hdr;
+ stp->codev = codev;
return 0;
}
@@ -4621,7 +4681,7 @@ final_touch(LoaderState* stp)
int on_load = stp->on_load;
unsigned catches;
Uint index;
- BeamInstr* code = stp->code;
+ BeamInstr* codev = stp->codev;
Module* modp;
/*
@@ -4631,10 +4691,10 @@ final_touch(LoaderState* stp)
index = stp->catches;
catches = BEAM_CATCHES_NIL;
while (index != 0) {
- BeamInstr next = code[index];
- code[index] = BeamOpCode(op_catch_yf);
- catches = beam_catches_cons((BeamInstr *)code[index+2], catches);
- code[index+2] = make_catch(catches);
+ BeamInstr next = codev[index];
+ codev[index] = BeamOpCode(op_catch_yf);
+ catches = beam_catches_cons((BeamInstr *)codev[index+2], catches);
+ codev[index+2] = make_catch(catches);
index = next;
}
modp = erts_put_module(stp->module);
@@ -4685,8 +4745,8 @@ final_touch(LoaderState* stp)
current = stp->import[i].patches;
while (current != 0) {
ASSERT(current < stp->ci);
- next = stp->code[current];
- stp->code[current] = import;
+ next = stp->codev[current];
+ stp->codev[current] = import;
current = next;
}
}
@@ -4699,7 +4759,7 @@ final_touch(LoaderState* stp)
for (i = 0; i < stp->num_lambdas; i++) {
unsigned entry_label = stp->lambdas[i].label;
ErlFunEntry* fe = stp->lambdas[i].fe;
- BeamInstr* code_ptr = (BeamInstr *) (stp->code + stp->labels[entry_label].value);
+ BeamInstr* code_ptr = stp->codev + stp->labels[entry_label].value;
if (fe->address[0] != 0) {
/*
@@ -5323,7 +5383,7 @@ new_label(LoaderState* stp)
(void *) stp->labels,
stp->num_labels * sizeof(Label));
stp->labels[num].value = 0;
- stp->labels[num].patches = 0;
+ stp->labels[num].patches = -1;
return num;
}
@@ -5383,7 +5443,7 @@ erts_module_info_0(Process* p, Eterm module)
{
Module* modp;
ErtsCodeIndex code_ix = erts_active_code_ix();
- BeamInstr* code;
+ BeamCodeHeader* code_hdr;
Eterm *hp;
Eterm list = NIL;
Eterm tup;
@@ -5397,13 +5457,13 @@ erts_module_info_0(Process* p, Eterm module)
return THE_NON_VALUE;
}
- code = modp->curr.code;
- if (code == NULL) {
+ code_hdr = modp->curr.code_hdr;
+ if (code_hdr == NULL) {
return THE_NON_VALUE;
}
#define BUILD_INFO(What) \
- tup = get_module_info(p, code_ix, code, module, What); \
+ tup = get_module_info(p, code_ix, code_hdr, module, What); \
hp = HAlloc(p, 5); \
tup = TUPLE2(hp, What, tup); \
hp += 3; \
@@ -5426,7 +5486,7 @@ erts_module_info_1(Process* p, Eterm module, Eterm what)
{
Module* modp;
ErtsCodeIndex code_ix = erts_active_code_ix();
- BeamInstr* code;
+ BeamCodeHeader* code_hdr;
if (is_not_atom(module)) {
return THE_NON_VALUE;
@@ -5437,34 +5497,34 @@ erts_module_info_1(Process* p, Eterm module, Eterm what)
return THE_NON_VALUE;
}
- code = modp->curr.code;
- if (code == NULL) {
+ code_hdr = modp->curr.code_hdr;
+ if (code_hdr == NULL) {
return THE_NON_VALUE;
}
- return get_module_info(p, code_ix, code, module, what);
+ return get_module_info(p, code_ix, code_hdr, module, what);
}
static Eterm
-get_module_info(Process* p, ErtsCodeIndex code_ix, BeamInstr* code,
+get_module_info(Process* p, ErtsCodeIndex code_ix, BeamCodeHeader* code_hdr,
Eterm module, Eterm what)
{
if (what == am_module) {
return module;
} else if (what == am_md5) {
- return md5_of_module(p, code);
+ return md5_of_module(p, code_hdr);
} else if (what == am_exports) {
return exported_from_module(p, code_ix, module);
} else if (what == am_functions) {
- return functions_in_module(p, code);
+ return functions_in_module(p, code_hdr);
} else if (what == am_attributes) {
- return attributes_for_module(p, code);
+ return attributes_for_module(p, code_hdr);
} else if (what == am_compile) {
- return compilation_info_for_module(p, code);
+ return compilation_info_for_module(p, code_hdr);
} else if (what == am_native_addresses) {
- return native_addresses(p, code);
+ return native_addresses(p, code_hdr);
} else if (what == am_native) {
- return has_native(code);
+ return has_native(code_hdr);
}
return THE_NON_VALUE;
}
@@ -5476,7 +5536,7 @@ get_module_info(Process* p, ErtsCodeIndex code_ix, BeamInstr* code,
Eterm
functions_in_module(Process* p, /* Process whose heap to use. */
- BeamInstr* code)
+ BeamCodeHeader* code_hdr)
{
int i;
Uint num_functions;
@@ -5485,12 +5545,12 @@ functions_in_module(Process* p, /* Process whose heap to use. */
Eterm* hp_end;
Eterm result = NIL;
- num_functions = code[MI_NUM_FUNCTIONS];
+ num_functions = code_hdr->num_functions;
need = 5*num_functions;
hp = HAlloc(p, need);
hp_end = hp + need;
for (i = num_functions-1; i >= 0 ; i--) {
- BeamInstr* func_info = (BeamInstr *) code[MI_FUNCTIONS+i];
+ BeamInstr* func_info = code_hdr->functions[i];
Eterm name = (Eterm) func_info[3];
int arity = (int) func_info[4];
Eterm tuple;
@@ -5516,11 +5576,11 @@ functions_in_module(Process* p, /* Process whose heap to use. */
*/
static Eterm
-has_native(BeamInstr *code)
+has_native(BeamCodeHeader *code_hdr)
{
Eterm result = am_false;
#ifdef HIPE
- if (erts_is_module_native(code)) {
+ if (erts_is_module_native(code_hdr)) {
result = am_true;
}
#endif
@@ -5528,15 +5588,15 @@ has_native(BeamInstr *code)
}
int
-erts_is_module_native(BeamInstr* code)
+erts_is_module_native(BeamCodeHeader* code_hdr)
{
Uint i, num_functions;
/* Check NativeAdress of first real function in module */
- if (code != NULL) {
- num_functions = code[MI_NUM_FUNCTIONS];
+ if (code_hdr != NULL) {
+ num_functions = code_hdr->num_functions;
for (i=0; i<num_functions; i++) {
- BeamInstr* func_info = (BeamInstr *) code[MI_FUNCTIONS+i];
+ BeamInstr* func_info = (BeamInstr *) code_hdr->functions[i];
Eterm name = (Eterm) func_info[3];
if (is_atom(name)) {
return func_info[1] != 0;
@@ -5553,7 +5613,7 @@ erts_is_module_native(BeamInstr* code)
*/
static Eterm
-native_addresses(Process* p, BeamInstr* code)
+native_addresses(Process* p, BeamCodeHeader* code_hdr)
{
int i;
Eterm* hp;
@@ -5562,12 +5622,12 @@ native_addresses(Process* p, BeamInstr* code)
Eterm* hp_end;
Eterm result = NIL;
- num_functions = code[MI_NUM_FUNCTIONS];
+ num_functions = code_hdr->num_functions;
need = (6+BIG_UINT_HEAP_SIZE)*num_functions;
hp = HAlloc(p, need);
hp_end = hp + need;
for (i = num_functions-1; i >= 0 ; i--) {
- BeamInstr* func_info = (BeamInstr *) code[MI_FUNCTIONS+i];
+ BeamInstr* func_info = code_hdr->functions[i];
Eterm name = (Eterm) func_info[3];
int arity = (int) func_info[4];
Eterm tuple;
@@ -5633,15 +5693,15 @@ exported_from_module(Process* p, /* Process whose heap to use. */
Eterm
attributes_for_module(Process* p, /* Process whose heap to use. */
- BeamInstr* code)
+ BeamCodeHeader* code_hdr)
{
byte* ext;
Eterm result = NIL;
- ext = (byte *) code[MI_ATTR_PTR];
+ ext = code_hdr->attr_ptr;
if (ext != NULL) {
ErtsHeapFactory factory;
- erts_factory_proc_prealloc_init(&factory, p, code[MI_ATTR_SIZE_ON_HEAP]);
+ erts_factory_proc_prealloc_init(&factory, p, code_hdr->attr_size_on_heap);
result = erts_decode_ext(&factory, &ext);
if (is_value(result)) {
erts_factory_close(&factory);
@@ -5656,15 +5716,15 @@ attributes_for_module(Process* p, /* Process whose heap to use. */
Eterm
compilation_info_for_module(Process* p, /* Process whose heap to use. */
- BeamInstr* code)
+ BeamCodeHeader* code_hdr)
{
byte* ext;
Eterm result = NIL;
- ext = (byte *) code[MI_COMPILE_PTR];
+ ext = code_hdr->compile_ptr;
if (ext != NULL) {
ErtsHeapFactory factory;
- erts_factory_proc_prealloc_init(&factory, p, code[MI_COMPILE_SIZE_ON_HEAP]);
+ erts_factory_proc_prealloc_init(&factory, p, code_hdr->compile_size_on_heap);
result = erts_decode_ext(&factory, &ext);
if (is_value(result)) {
erts_factory_close(&factory);
@@ -5679,9 +5739,9 @@ compilation_info_for_module(Process* p, /* Process whose heap to use. */
Eterm
md5_of_module(Process* p, /* Process whose heap to use. */
- BeamInstr* code)
+ BeamCodeHeader* code_hdr)
{
- return new_binary(p, (byte *) code[MI_MD5_PTR], MD5_SIZE);
+ return new_binary(p, code_hdr->md5_ptr, MD5_SIZE);
}
/*
@@ -5892,7 +5952,7 @@ static byte*
stub_copy_info(LoaderState* stp,
int chunk, /* Chunk: ATTR_CHUNK or COMPILE_CHUNK */
byte* info, /* Where to store info. */
- BeamInstr* ptr_word, /* Where to store pointer into info. */
+ byte** ptr_word, /* Where to store pointer into info. */
BeamInstr* size_word, /* Where to store size into info. */
BeamInstr* size_on_heap_word) /* Where to store size on heap. */
{
@@ -5900,7 +5960,7 @@ stub_copy_info(LoaderState* stp,
Uint size = stp->chunks[chunk].size;
if (size != 0) {
memcpy(info, stp->chunks[chunk].start, size);
- *ptr_word = (BeamInstr) info;
+ *ptr_word = info;
decoded_size = erts_decode_ext_size(info, size);
if (decoded_size < 0) {
return 0;
@@ -6155,11 +6215,10 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info)
BeamInstr Patchlist;
Eterm MD5Bin;
Eterm* tp;
- BeamInstr* code = NULL;
- BeamInstr* ptrs;
+ BeamCodeHeader* code_hdr;
+ BeamInstr* code_base;
BeamInstr* fp;
byte* info;
- Uint ci;
int n;
int code_size;
int rval;
@@ -6237,39 +6296,39 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info)
* Allocate memory for the stub module.
*/
- code_size = ((WORDS_PER_FUNCTION+1)*n + MI_FUNCTIONS + 2) * sizeof(BeamInstr);
- code_size += stp->chunks[ATTR_CHUNK].size;
- code_size += stp->chunks[COMPILE_CHUNK].size;
- code_size += MD5_SIZE;
- code = erts_alloc_fnf(ERTS_ALC_T_CODE, code_size);
- if (!code) {
+ code_size = (offsetof(BeamCodeHeader,functions)
+ + ((n+1) * sizeof(BeamInstr*))
+ + (WORDS_PER_FUNCTION*n + 1) * sizeof(BeamInstr)
+ + stp->chunks[ATTR_CHUNK].size
+ + stp->chunks[COMPILE_CHUNK].size
+ + MD5_SIZE);
+ code_hdr = erts_alloc_fnf(ERTS_ALC_T_CODE, code_size);
+ if (!code_hdr) {
goto error;
}
/*
- * Initialize code area.
+ * Initialize code header.
*/
- code[MI_NUM_FUNCTIONS] = n;
- code[MI_ATTR_PTR] = 0;
- code[MI_ATTR_SIZE] = 0;
- code[MI_ATTR_SIZE_ON_HEAP] = 0;
- code[MI_COMPILE_PTR] = 0;
- code[MI_COMPILE_SIZE] = 0;
- code[MI_COMPILE_SIZE_ON_HEAP] = 0;
- code[MI_LITERALS_START] = 0;
- code[MI_LITERALS_END] = 0;
- code[MI_LITERALS_OFF_HEAP] = 0;
- code[MI_ON_LOAD_FUNCTION_PTR] = 0;
- code[MI_MD5_PTR] = 0;
- ci = MI_FUNCTIONS + n + 1;
+ code_hdr->num_functions = n;
+ code_hdr->attr_ptr = NULL;
+ code_hdr->attr_size = 0;
+ code_hdr->attr_size_on_heap = 0;
+ code_hdr->compile_ptr = NULL;
+ code_hdr->compile_size = 0;
+ code_hdr->compile_size_on_heap = 0;
+ code_hdr->literals_start = NULL;
+ code_hdr->literals_end = NULL;
+ code_hdr->literals_off_heap = 0;
+ code_hdr->on_load_function_ptr = NULL;
+ code_hdr->md5_ptr = NULL;
/*
* Make stubs for all functions.
*/
- ptrs = code + MI_FUNCTIONS;
- fp = code + ci;
+ fp = code_base = (BeamInstr*) &code_hdr->functions[n+1];
for (i = 0; i < n; i++) {
Eterm* listp;
Eterm tuple;
@@ -6312,7 +6371,7 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info)
* Set the pointer and make the stub. Put a return instruction
* as the body until we know what kind of trap we should put there.
*/
- ptrs[i] = (BeamInstr) fp;
+ code_hdr->functions[i] = fp;
#ifdef HIPE
op = (Eterm) BeamOpCode(op_hipe_trap_call); /* Might be changed later. */
#else
@@ -6325,7 +6384,7 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info)
* Insert the last pointer and the int_code_end instruction.
*/
- ptrs[i] = (BeamInstr) fp;
+ code_hdr->functions[i] = fp;
*fp++ = (BeamInstr) BeamOp(op_int_code_end);
/*
@@ -6334,16 +6393,16 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info)
info = (byte *) fp;
info = stub_copy_info(stp, ATTR_CHUNK, info,
- code+MI_ATTR_PTR,
- code+MI_ATTR_SIZE,
- code+MI_ATTR_SIZE_ON_HEAP);
+ &code_hdr->attr_ptr,
+ &code_hdr->attr_size,
+ &code_hdr->attr_size_on_heap);
if (info == NULL) {
goto error;
}
info = stub_copy_info(stp, COMPILE_CHUNK, info,
- code+MI_COMPILE_PTR,
- code+MI_COMPILE_SIZE,
- code+MI_COMPILE_SIZE_ON_HEAP);
+ &code_hdr->compile_ptr,
+ &code_hdr->compile_size,
+ &code_hdr->compile_size_on_heap);
if (info == NULL) {
goto error;
}
@@ -6352,7 +6411,7 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info)
byte *md5 = NULL;
if ((md5 = erts_get_aligned_binary_bytes(MD5Bin, &tmp)) != NULL) {
sys_memcpy(info, md5, MD5_SIZE);
- code[MI_MD5_PTR] = (BeamInstr) info;
+ code_hdr->md5_ptr = info;
}
erts_free_aligned_binary_bytes(tmp);
}
@@ -6361,7 +6420,7 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info)
* Insert the module in the module table.
*/
- rval = insert_new_code(p, 0, p->group_leader, Mod, code, code_size);
+ rval = insert_new_code(p, 0, p->group_leader, Mod, code_hdr, code_size);
if (rval != NIL) {
goto error;
}
@@ -6370,7 +6429,7 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info)
* Export all stub functions and insert the correct type of HiPE trap.
*/
- fp = code + ci;
+ fp = code_base;
for (i = 0; i < n; i++) {
stub_final_touch(stp, fp);
fp += WORDS_PER_FUNCTION;
diff --git a/erts/emulator/beam/beam_load.h b/erts/emulator/beam/beam_load.h
index eedb5ee4cd..22ab71c868 100644
--- a/erts/emulator/beam/beam_load.h
+++ b/erts/emulator/beam/beam_load.h
@@ -24,7 +24,6 @@
#include "beam_opcodes.h"
#include "erl_process.h"
-int erts_is_module_native(BeamInstr* code);
Eterm beam_make_current_old(Process *c_p, ErtsProcLocks c_p_locks,
Eterm module);
@@ -61,72 +60,81 @@ extern BeamInstr* em_call_nif;
/* Total code size in bytes */
extern Uint erts_total_code_size;
-/*
- * Index into start of code chunks which contains additional information
- * about the loaded module.
- *
- * First number of functions.
- */
-
-#define MI_NUM_FUNCTIONS 0
-
-/*
- * The attributes retrieved by Mod:module_info(attributes).
- */
-
-#define MI_ATTR_PTR 1
-#define MI_ATTR_SIZE 2
-#define MI_ATTR_SIZE_ON_HEAP 3
-
-/*
- * The compilation information retrieved by Mod:module_info(compile).
- */
-
-#define MI_COMPILE_PTR 4
-#define MI_COMPILE_SIZE 5
-#define MI_COMPILE_SIZE_ON_HEAP 6
-
-/*
- * Literal area (constant pool).
- */
-#define MI_LITERALS_START 7
-#define MI_LITERALS_END 8
-#define MI_LITERALS_OFF_HEAP 9
-
-/*
- * Pointer to the on_load function (or NULL if none).
- */
-#define MI_ON_LOAD_FUNCTION_PTR 10
-
-/*
- * Pointer to the line table (or NULL if none).
- */
-#define MI_LINE_TABLE 11
-/*
- * Pointer to the module MD5 sum (16 bytes)
- */
-#define MI_MD5_PTR 12
+typedef struct BeamCodeLineTab_ BeamCodeLineTab;
/*
- * Start of function pointer table. This table contains pointers to
- * all functions in the module plus an additional pointer just beyond
- * the end of the last function.
- *
- * The actual loaded code (for the first function) start just beyond
- * this table.
+ * Header of code chunks which contains additional information
+ * about the loaded module.
*/
-
-#define MI_FUNCTIONS 13
+typedef struct beam_code_header {
+ /*
+ * Number of functions.
+ */
+ UWord num_functions;
+
+ /*
+ * The attributes retrieved by Mod:module_info(attributes).
+ */
+ byte* attr_ptr;
+ UWord attr_size;
+ UWord attr_size_on_heap;
+
+ /*
+ * The compilation information retrieved by Mod:module_info(compile).
+ */
+ byte* compile_ptr;
+ UWord compile_size;
+ UWord compile_size_on_heap;
+
+ /*
+ * Literal area (constant pool).
+ */
+ Eterm* literals_start;
+ Eterm* literals_end;
+ struct erl_off_heap_header* literals_off_heap;
+
+ /*
+ * Pointer to the on_load function (or NULL if none).
+ */
+ BeamInstr* on_load_function_ptr;
+
+ /*
+ * Pointer to the line table (or NULL if none).
+ */
+ BeamCodeLineTab* line_table;
+
+ /*
+ * Pointer to the module MD5 sum (16 bytes)
+ */
+ byte* md5_ptr;
+
+ /*
+ * Start of function pointer table. This table contains pointers to
+ * all functions in the module plus an additional pointer just beyond
+ * the end of the last function.
+ *
+ * The actual loaded code (for the first function) start just beyond
+ * this table.
+ */
+ BeamInstr* functions[1];
+
+}BeamCodeHeader;
+
+int erts_is_module_native(BeamCodeHeader* code);
/*
* Layout of the line table.
*/
-
-#define MI_LINE_FNAME_PTR 0
-#define MI_LINE_LOC_TAB 1
-#define MI_LINE_LOC_SIZE 2
-#define MI_LINE_FUNC_TAB 3
+struct BeamCodeLineTab_ {
+ Eterm* fname_ptr;
+ int loc_size;
+ union {
+ Uint16* p2;
+ Uint32* p4;
+ }loc_tab;
+ const BeamInstr** func_tab[1];
+};
#define LINE_INVALID_LOCATION (0)
diff --git a/erts/emulator/beam/beam_ranges.c b/erts/emulator/beam/beam_ranges.c
index 19079ba150..5a2b66727a 100644
--- a/erts/emulator/beam/beam_ranges.c
+++ b/erts/emulator/beam/beam_ranges.c
@@ -37,8 +37,8 @@ typedef struct {
#define RANGE_END(R) ((BeamInstr*)erts_smp_atomic_read_nob(&(R)->end))
static Range* find_range(BeamInstr* pc);
-static void lookup_loc(FunctionInfo* fi, BeamInstr* pc,
- BeamInstr* modp, int idx);
+static void lookup_loc(FunctionInfo* fi, const BeamInstr* pc,
+ BeamCodeHeader*, int idx);
/*
* The following variables keep a sorted list of address ranges for
@@ -241,6 +241,7 @@ erts_lookup_function_info(FunctionInfo* fi, BeamInstr* pc, int full_info)
BeamInstr** high;
BeamInstr** mid;
Range* rp;
+ BeamCodeHeader* hdr;
fi->current = NULL;
fi->needed = 5;
@@ -249,9 +250,10 @@ erts_lookup_function_info(FunctionInfo* fi, BeamInstr* pc, int full_info)
if (rp == 0) {
return;
}
+ hdr = (BeamCodeHeader*) rp->start;
- low = (BeamInstr **) (rp->start + MI_FUNCTIONS);
- high = low + rp->start[MI_NUM_FUNCTIONS];
+ low = hdr->functions;
+ high = low + hdr->num_functions;
while (low < high) {
mid = low + (high-low) / 2;
if (pc < mid[0]) {
@@ -259,10 +261,9 @@ erts_lookup_function_info(FunctionInfo* fi, BeamInstr* pc, int full_info)
} else if (pc < mid[1]) {
fi->current = mid[0]+2;
if (full_info) {
- BeamInstr** fp = (BeamInstr **) (rp->start +
- MI_FUNCTIONS);
+ BeamInstr** fp = hdr->functions;
int idx = mid - fp;
- lookup_loc(fi, pc, rp->start, idx);
+ lookup_loc(fi, pc, hdr, idx);
}
return;
} else {
@@ -295,39 +296,34 @@ find_range(BeamInstr* pc)
}
static void
-lookup_loc(FunctionInfo* fi, BeamInstr* orig_pc, BeamInstr* modp, int idx)
+lookup_loc(FunctionInfo* fi, const BeamInstr* pc,
+ BeamCodeHeader* code_hdr, int idx)
{
- Eterm* line = (Eterm *) modp[MI_LINE_TABLE];
- Eterm* low;
- Eterm* high;
- Eterm* mid;
- Eterm pc;
+ BeamCodeLineTab* lt = code_hdr->line_table;
+ const BeamInstr** low;
+ const BeamInstr** high;
+ const BeamInstr** mid;
- if (line == 0) {
+ if (lt == NULL) {
return;
}
- pc = (Eterm) (BeamInstr) orig_pc;
- fi->fname_ptr = (Eterm *) (BeamInstr) line[MI_LINE_FNAME_PTR];
- low = (Eterm *) (BeamInstr) line[MI_LINE_FUNC_TAB+idx];
- high = (Eterm *) (BeamInstr) line[MI_LINE_FUNC_TAB+idx+1];
+ fi->fname_ptr = lt->fname_ptr;
+ low = lt->func_tab[idx];
+ high = lt->func_tab[idx+1];
while (high > low) {
mid = low + (high-low) / 2;
if (pc < mid[0]) {
high = mid;
} else if (pc < mid[1]) {
int file;
- int index = mid - (Eterm *) (BeamInstr) line[MI_LINE_FUNC_TAB];
+ int index = mid - lt->func_tab[0];
- if (line[MI_LINE_LOC_SIZE] == 2) {
- Uint16* loc_table =
- (Uint16 *) (BeamInstr) line[MI_LINE_LOC_TAB];
- fi->loc = loc_table[index];
+ if (lt->loc_size == 2) {
+ fi->loc = lt->loc_tab.p2[index];
} else {
- Uint32* loc_table =
- (Uint32 *) (BeamInstr) line[MI_LINE_LOC_TAB];
- ASSERT(line[MI_LINE_LOC_SIZE] == 4);
- fi->loc = loc_table[index];
+ ASSERT(lt->loc_size == 4);
+ fi->loc = lt->loc_tab.p4[index];
}
if (fi->loc == LINE_INVALID_LOCATION) {
return;
diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c
index 453ac74c90..bb9165cd79 100644
--- a/erts/emulator/beam/bif.c
+++ b/erts/emulator/beam/bif.c
@@ -72,7 +72,7 @@ BIF_RETTYPE spawn_3(BIF_ALIST_3)
ErlSpawnOpts so;
Eterm pid;
- so.flags = 0;
+ so.flags = erts_default_spo_flags;
pid = erl_create_process(BIF_P, BIF_ARG_1, BIF_ARG_2, BIF_ARG_3, &so);
if (is_non_value(pid)) {
BIF_ERROR(BIF_P, so.error_code);
@@ -589,7 +589,7 @@ erts_queue_monitor_message(Process *p,
Eterm reason_copy, ref_copy, item_copy;
Uint reason_size, ref_size, item_size, heap_size;
ErlOffHeap *ohp;
- ErlHeapFragment *bp;
+ ErtsMessage *msgp;
reason_size = IS_CONST(reason) ? 0 : size_object(reason);
item_size = IS_CONST(item) ? 0 : size_object(item);
@@ -597,11 +597,8 @@ erts_queue_monitor_message(Process *p,
heap_size = 6+reason_size+ref_size+item_size;
- hp = erts_alloc_message_heap(heap_size,
- &bp,
- &ohp,
- p,
- p_locksp);
+ msgp = erts_alloc_message_heap(p, p_locksp, heap_size,
+ &hp, &ohp);
reason_copy = (IS_CONST(reason)
? reason
@@ -612,7 +609,7 @@ erts_queue_monitor_message(Process *p,
ref_copy = copy_struct(ref, ref_size, &hp, ohp);
tup = TUPLE5(hp, am_DOWN, ref_copy, type, item_copy, reason_copy);
- erts_queue_message(p, p_locksp, bp, tup, NIL);
+ erts_queue_message(p, p_locksp, msgp, tup, NIL);
}
static BIF_RETTYPE
@@ -841,7 +838,7 @@ BIF_RETTYPE spawn_link_3(BIF_ALIST_3)
ErlSpawnOpts so;
Eterm pid;
- so.flags = SPO_LINK;
+ so.flags = erts_default_spo_flags|SPO_LINK;
pid = erl_create_process(BIF_P, BIF_ARG_1, BIF_ARG_2, BIF_ARG_3, &so);
if (is_non_value(pid)) {
BIF_ERROR(BIF_P, so.error_code);
@@ -878,7 +875,7 @@ BIF_RETTYPE spawn_opt_1(BIF_ALIST_1)
/*
* Store default values for options.
*/
- so.flags = SPO_USE_ARGS;
+ so.flags = erts_default_spo_flags|SPO_USE_ARGS;
so.min_heap_size = H_MIN_SIZE;
so.min_vheap_size = BIN_VH_MIN_SIZE;
so.priority = PRIORITY_NORMAL;
@@ -913,6 +910,22 @@ BIF_RETTYPE spawn_opt_1(BIF_ALIST_1)
so.priority = PRIORITY_LOW;
else
goto error;
+ } else if (arg == am_message_queue_data) {
+ switch (val) {
+ case am_mixed:
+ so.flags &= ~(SPO_OFF_HEAP_MSGQ|SPO_ON_HEAP_MSGQ);
+ break;
+ case am_on_heap:
+ so.flags &= ~SPO_OFF_HEAP_MSGQ;
+ so.flags |= SPO_ON_HEAP_MSGQ;
+ break;
+ case am_off_heap:
+ so.flags &= ~SPO_ON_HEAP_MSGQ;
+ so.flags |= SPO_OFF_HEAP_MSGQ;
+ break;
+ default:
+ goto error;
+ }
} else if (arg == am_min_heap_size && is_small(val)) {
Sint min_heap_size = signed_val(val);
if (min_heap_size < 0) {
@@ -1691,6 +1704,12 @@ BIF_RETTYPE process_flag_2(BIF_ALIST_2)
}
BIF_RET(old_value);
}
+ else if (BIF_ARG_1 == am_message_queue_data) {
+ old_value = erts_change_message_queue_management(BIF_P, BIF_ARG_2);
+ if (is_non_value(old_value))
+ goto error;
+ BIF_RET(old_value);
+ }
else if (BIF_ARG_1 == am_sensitive) {
Uint is_sensitive;
if (BIF_ARG_2 == am_true) {
@@ -1931,7 +1950,7 @@ do_send(Process *p, Eterm to, Eterm msg, Eterm *refp, ErtsSendContext* ctx)
} else if (is_atom(to)) {
Eterm id = erts_whereis_name_to_id(p, to);
- rp = erts_proc_lookup(id);
+ rp = erts_proc_lookup_raw(id);
if (rp) {
if (IS_TRACED(p))
trace_send(p, to, msg);
@@ -2023,11 +2042,7 @@ do_send(Process *p, Eterm to, Eterm msg, Eterm *refp, ErtsSendContext* ctx)
if (ERTS_PROC_GET_SAVED_CALLS_BUF(p))
save_calls(p, &exp_send);
- if (SEQ_TRACE_TOKEN(p) != NIL
-#ifdef USE_VM_PROBES
- && SEQ_TRACE_TOKEN(p) != am_have_dt_utag
-#endif
- ) {
+ if (have_seqtrace(SEQ_TRACE_TOKEN(p))) {
seq_trace_update_send(p);
seq_trace_output(SEQ_TRACE_TOKEN(p), msg,
SEQ_TRACE_SEND, portid, p);
@@ -3824,11 +3839,9 @@ BIF_RETTYPE now_0(BIF_ALIST_0)
BIF_RETTYPE garbage_collect_0(BIF_ALIST_0)
{
- int reds;
-
FLAGS(BIF_P) |= F_NEED_FULLSWEEP;
- reds = erts_garbage_collect(BIF_P, 0, NULL, 0);
- BIF_RET2(am_true, reds);
+ erts_garbage_collect(BIF_P, 0, NULL, 0);
+ BIF_RET(am_true);
}
/**********************************************************************/
@@ -4224,6 +4237,7 @@ BIF_RETTYPE list_to_pid_1(BIF_ALIST_1)
goto bad;
enp = erts_find_or_insert_node(dep->sysname, dep->creation);
+ ASSERT(enp != erts_this_node);
etp = (ExternalThing *) HAlloc(BIF_P, EXTERNAL_THING_HEAD_SIZE + 1);
etp->header = make_external_pid_header(1);
@@ -4479,7 +4493,7 @@ BIF_RETTYPE system_flag_2(BIF_ALIST_2)
}
} else if (BIF_ARG_1 == make_small(1)) {
int i, max;
- ErlMessage* mp;
+ ErtsMessage* mp;
erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
erts_smp_thr_progress_block();
diff --git a/erts/emulator/beam/bif.h b/erts/emulator/beam/bif.h
index c6ed60376a..a62eddf36b 100644
--- a/erts/emulator/beam/bif.h
+++ b/erts/emulator/beam/bif.h
@@ -54,22 +54,24 @@ extern Export *erts_convert_time_unit_trap;
(p)->fcalls = -CONTEXT_REDS; \
} while(0)
-
-#define ERTS_VBUMP_ALL_REDS(p) \
+#define ERTS_VBUMP_ALL_REDS_INTERNAL(p, fcalls) \
do { \
if (!ERTS_PROC_GET_SAVED_CALLS_BUF((p))) { \
- if ((p)->fcalls > 0) \
- ERTS_PROC_GET_SCHDATA((p))->virtual_reds += (p)->fcalls; \
- (p)->fcalls = 0; \
+ if ((fcalls) > 0) \
+ ERTS_PROC_GET_SCHDATA((p))->virtual_reds += (fcalls); \
+ (fcalls) = 0; \
} \
else { \
- if ((p)->fcalls > -CONTEXT_REDS) \
+ if ((fcalls) > -CONTEXT_REDS) \
ERTS_PROC_GET_SCHDATA((p))->virtual_reds \
- += ((p)->fcalls - (-CONTEXT_REDS)); \
- (p)->fcalls = -CONTEXT_REDS; \
+ += ((fcalls) - (-CONTEXT_REDS)); \
+ (fcalls) = -CONTEXT_REDS; \
} \
} while(0)
+#define ERTS_VBUMP_ALL_REDS(p) \
+ ERTS_VBUMP_ALL_REDS_INTERNAL((p), (p)->fcalls)
+
#define BUMP_REDS(p, gc) do { \
ASSERT(p); \
ERTS_SMP_LC_ASSERT(ERTS_PROC_LOCK_MAIN & erts_proc_lc_my_proc_locks(p));\
@@ -110,10 +112,34 @@ do { \
} \
} while(0)
-#define ERTS_BIF_REDS_LEFT(p) \
+#define ERTS_VBUMP_LEAVE_REDS_INTERNAL(P, Reds, FCalls) \
+ do { \
+ if (ERTS_PROC_GET_SAVED_CALLS_BUF((P))) { \
+ int nreds__ = ((int)(Reds)) - CONTEXT_REDS; \
+ if ((FCalls) > nreds__) { \
+ ERTS_PROC_GET_SCHDATA((P))->virtual_reds \
+ += (FCalls) - nreds__; \
+ (FCalls) = nreds__; \
+ } \
+ } \
+ else { \
+ if ((FCalls) > (Reds)) { \
+ ERTS_PROC_GET_SCHDATA((P))->virtual_reds \
+ += (FCalls) - (Reds); \
+ (FCalls) = (Reds); \
+ } \
+ } \
+ } while (0)
+
+#define ERTS_VBUMP_LEAVE_REDS(P, Reds) \
+ ERTS_VBUMP_LEAVE_REDS_INTERNAL(P, Reds, (P)->fcalls)
+
+#define ERTS_REDS_LEFT(p, FCalls) \
(ERTS_PROC_GET_SAVED_CALLS_BUF((p)) \
- ? ((p)->fcalls > -CONTEXT_REDS ? ((p)->fcalls - (-CONTEXT_REDS)) : 0)\
- : ((p)->fcalls > 0 ? (p)->fcalls : 0))
+ ? ((FCalls) > -CONTEXT_REDS ? ((FCalls) - (-CONTEXT_REDS)) : 0) \
+ : ((FCalls) > 0 ? (FCalls) : 0))
+
+#define ERTS_BIF_REDS_LEFT(p) ERTS_REDS_LEFT(p, p->fcalls)
#define BIF_RET2(x, gc) do { \
BUMP_REDS(BIF_P, (gc)); \
diff --git a/erts/emulator/beam/bif.tab b/erts/emulator/beam/bif.tab
index 884555dee2..0aee8681c6 100644
--- a/erts/emulator/beam/bif.tab
+++ b/erts/emulator/beam/bif.tab
@@ -167,7 +167,7 @@ bif erts_internal:request_system_task/3
bif erts_internal:check_process_code/2
bif erts_internal:map_to_tuple_keys/1
-bif erts_internal:map_type/1
+bif erts_internal:term_type/1
bif erts_internal:map_hashmap_children/1
bif erts_internal:time_unit/0
@@ -639,14 +639,17 @@ bif ets:update_counter/4
bif erts_debug:map_info/1
#
-# Obsolete
+# New in 19.0
#
-bif erlang:hash/2
+bif erlang:copy_literals/2
+bif binary:split/2
+bif binary:split/3
+bif erts_debug:size_shared/1
+bif erts_debug:copy_shared/1
#
-# New in 19.0
+# Obsolete
#
-bif binary:split/2
-bif binary:split/3
+bif erlang:hash/2
diff --git a/erts/emulator/beam/binary.c b/erts/emulator/beam/binary.c
index e670fbf31c..d3e481c7f9 100644
--- a/erts/emulator/beam/binary.c
+++ b/erts/emulator/beam/binary.c
@@ -34,6 +34,9 @@
#include "erl_binary.h"
#include "erl_bits.h"
+#define L2B_B2L_MIN_EXEC_REDS (CONTEXT_REDS/4)
+#define L2B_B2L_RESCHED_REDS (CONTEXT_REDS/40)
+
static Export binary_to_list_continue_export;
static Export list_to_binary_continue_export;
@@ -415,10 +418,10 @@ binary_to_list_chunk(Process *c_p,
}
static ERTS_INLINE BIF_RETTYPE
-binary_to_list(Process *c_p, Eterm *hp, Eterm tail, byte *bytes, Uint size, Uint bitoffs)
+binary_to_list(Process *c_p, Eterm *hp, Eterm tail, byte *bytes,
+ Uint size, Uint bitoffs, int reds_left, int one_chunk)
{
- int reds_left = ERTS_BIF_REDS_LEFT(c_p);
- if (size < reds_left*ERTS_B2L_BYTES_PER_REDUCTION) {
+ if (one_chunk) {
Eterm res;
BIF_RETTYPE ret;
int bump_reds = (size - 1)/ERTS_B2L_BYTES_PER_REDUCTION + 1;
@@ -472,11 +475,29 @@ BIF_RETTYPE binary_to_list_1(BIF_ALIST_1)
Uint size;
Uint bitsize;
Uint bitoffs;
+ int reds_left;
+ int one_chunk;
if (is_not_binary(BIF_ARG_1)) {
goto error;
}
+
size = binary_size(BIF_ARG_1);
+ reds_left = ERTS_BIF_REDS_LEFT(BIF_P);
+ one_chunk = size < reds_left*ERTS_B2L_BYTES_PER_REDUCTION;
+ if (!one_chunk) {
+ if (size < L2B_B2L_MIN_EXEC_REDS*ERTS_B2L_BYTES_PER_REDUCTION) {
+ if (reds_left <= L2B_B2L_RESCHED_REDS) {
+ /* Yield and do it with full context reds... */
+ ERTS_BIF_YIELD1(bif_export[BIF_binary_to_list_1],
+ BIF_P, BIF_ARG_1);
+ }
+ /* Allow a bit more reductions... */
+ one_chunk = 1;
+ reds_left = L2B_B2L_MIN_EXEC_REDS;
+ }
+ }
+
ERTS_GET_REAL_BIN(BIF_ARG_1, real_bin, offset, bitoffs, bitsize);
if (bitsize != 0) {
goto error;
@@ -486,7 +507,8 @@ BIF_RETTYPE binary_to_list_1(BIF_ALIST_1)
} else {
Eterm* hp = HAlloc(BIF_P, 2 * size);
byte* bytes = binary_bytes(real_bin)+offset;
- return binary_to_list(BIF_P, hp, NIL, bytes, size, bitoffs);
+ return binary_to_list(BIF_P, hp, NIL, bytes, size,
+ bitoffs, reds_left, one_chunk);
}
error:
@@ -505,6 +527,8 @@ BIF_RETTYPE binary_to_list_3(BIF_ALIST_3)
Uint start;
Uint stop;
Eterm* hp;
+ int reds_left;
+ int one_chunk;
if (is_not_binary(BIF_ARG_1)) {
goto error;
@@ -513,6 +537,21 @@ BIF_RETTYPE binary_to_list_3(BIF_ALIST_3)
goto error;
}
size = binary_size(BIF_ARG_1);
+ reds_left = ERTS_BIF_REDS_LEFT(BIF_P);
+ one_chunk = size < reds_left*ERTS_B2L_BYTES_PER_REDUCTION;
+ if (!one_chunk) {
+ if (size < L2B_B2L_MIN_EXEC_REDS*ERTS_B2L_BYTES_PER_REDUCTION) {
+ if (reds_left <= L2B_B2L_RESCHED_REDS) {
+ /* Yield and do it with full context reds... */
+ ERTS_BIF_YIELD3(bif_export[BIF_binary_to_list_3],
+ BIF_P, BIF_ARG_1, BIF_ARG_2, BIF_ARG_3);
+ }
+ /* Allow a bit more reductions... */
+ one_chunk = 1;
+ reds_left = L2B_B2L_MIN_EXEC_REDS;
+ }
+ }
+
ERTS_GET_BINARY_BYTES(BIF_ARG_1, bytes, bitoffs, bitsize);
if (start < 1 || start > size || stop < 1 ||
stop > size || stop < start ) {
@@ -520,7 +559,8 @@ BIF_RETTYPE binary_to_list_3(BIF_ALIST_3)
}
i = stop-start+1;
hp = HAlloc(BIF_P, 2*i);
- return binary_to_list(BIF_P, hp, NIL, bytes+start-1, i, bitoffs);
+ return binary_to_list(BIF_P, hp, NIL, bytes+start-1, i,
+ bitoffs, reds_left, one_chunk);
error:
BIF_ERROR(BIF_P, BADARG);
}
@@ -537,11 +577,27 @@ BIF_RETTYPE bitstring_to_list_1(BIF_ALIST_1)
byte* bytes;
Eterm previous = NIL;
Eterm* hp;
+ int reds_left;
+ int one_chunk;
if (is_not_binary(BIF_ARG_1)) {
BIF_ERROR(BIF_P, BADARG);
}
size = binary_size(BIF_ARG_1);
+ reds_left = ERTS_BIF_REDS_LEFT(BIF_P);
+ one_chunk = size < reds_left*ERTS_B2L_BYTES_PER_REDUCTION;
+ if (!one_chunk) {
+ if (size < L2B_B2L_MIN_EXEC_REDS*ERTS_B2L_BYTES_PER_REDUCTION) {
+ if (reds_left <= L2B_B2L_RESCHED_REDS) {
+ /* Yield and do it with full context reds... */
+ ERTS_BIF_YIELD1(bif_export[BIF_bitstring_to_list_1],
+ BIF_P, BIF_ARG_1);
+ }
+ /* Allow a bit more reductions... */
+ one_chunk = 1;
+ reds_left = L2B_B2L_MIN_EXEC_REDS;
+ }
+ }
ERTS_GET_REAL_BIN(BIF_ARG_1, real_bin, offset, bitoffs, bitsize);
bytes = binary_bytes(real_bin)+offset;
if (bitsize == 0) {
@@ -566,7 +622,8 @@ BIF_RETTYPE bitstring_to_list_1(BIF_ALIST_1)
hp += 2;
}
- return binary_to_list(BIF_P, hp, previous, bytes, size, bitoffs);
+ return binary_to_list(BIF_P, hp, previous, bytes, size,
+ bitoffs, reds_left, one_chunk);
}
@@ -795,8 +852,19 @@ static BIF_RETTYPE list_to_binary_continue(BIF_ALIST_1)
BIF_RETTYPE erts_list_to_binary_bif(Process *c_p, Eterm arg, Export *bif)
{
+ int orig_reds_left = ERTS_BIF_REDS_LEFT(c_p);
BIF_RETTYPE ret;
+ if (orig_reds_left < L2B_B2L_MIN_EXEC_REDS) {
+ if (orig_reds_left <= L2B_B2L_RESCHED_REDS) {
+ /* Yield and do it with full context reds... */
+ ERTS_BIF_PREP_YIELD1(ret, bif, c_p, arg);
+ return ret;
+ }
+ /* Allow a bit more reductions... */
+ orig_reds_left = L2B_B2L_MIN_EXEC_REDS;
+ }
+
if (is_nil(arg))
ERTS_BIF_PREP_RET(ret, new_binary(c_p, (byte *) "", 0));
else if (is_not_list(arg))
@@ -818,7 +886,6 @@ BIF_RETTYPE erts_list_to_binary_bif(Process *c_p, Eterm arg, Export *bif)
bif,
erts_iolist_size_yielding,
erts_iolist_to_buf_yielding);
- int orig_reds_left = ERTS_BIF_REDS_LEFT(c_p);
/*
* First try to do it all at once without having to use
diff --git a/erts/emulator/beam/break.c b/erts/emulator/beam/break.c
index 4ce9d24479..2c8ecf04be 100644
--- a/erts/emulator/beam/break.c
+++ b/erts/emulator/beam/break.c
@@ -252,7 +252,7 @@ print_process_info(int to, void *to_arg, Process *p)
/* display the message queue only if there is anything in it */
if (!ERTS_IS_CRASH_DUMPING && p->msg.first != NULL && !garbing) {
- ErlMessage* mp;
+ ErtsMessage* mp;
erts_print(to, to_arg, "Message queue: [");
for (mp = p->msg.first; mp; mp = mp->next)
erts_print(to, to_arg, mp->next ? "%T," : "%T", ERL_MESSAGE_TERM(mp));
@@ -323,7 +323,7 @@ print_process_info(int to, void *to_arg, Process *p)
erts_print(to, to_arg, "Heap unused: %bpu\n", (p->hend - p->htop));
erts_print(to, to_arg, "OldHeap unused: %bpu\n",
(OLD_HEAP(p) == NULL) ? 0 : (OLD_HEND(p) - OLD_HTOP(p)) );
- erts_print(to, to_arg, "Memory: %beu\n", erts_process_memory(p));
+ erts_print(to, to_arg, "Memory: %beu\n", erts_process_memory(p, !0));
if (garbing) {
print_garb_info(to, to_arg, p);
@@ -381,7 +381,7 @@ loaded(int to, void *to_arg)
int i;
int old = 0;
int cur = 0;
- BeamInstr* code;
+ BeamCodeHeader* code;
Module* modp;
ErtsCodeIndex code_ix;
@@ -439,30 +439,30 @@ loaded(int to, void *to_arg)
erts_print(to, to_arg, "\n");
erts_print(to, to_arg, "Current size: %d\n",
modp->curr.code_length);
- code = modp->curr.code;
- if (code != NULL && code[MI_ATTR_PTR]) {
+ code = modp->curr.code_hdr;
+ if (code != NULL && code->attr_ptr) {
erts_print(to, to_arg, "Current attributes: ");
- dump_attributes(to, to_arg, (byte *) code[MI_ATTR_PTR],
- code[MI_ATTR_SIZE]);
+ dump_attributes(to, to_arg, code->attr_ptr,
+ code->attr_size);
}
- if (code != NULL && code[MI_COMPILE_PTR]) {
+ if (code != NULL && code->compile_ptr) {
erts_print(to, to_arg, "Current compilation info: ");
- dump_attributes(to, to_arg, (byte *) code[MI_COMPILE_PTR],
- code[MI_COMPILE_SIZE]);
+ dump_attributes(to, to_arg, code->compile_ptr,
+ code->compile_size);
}
if (modp->old.code_length != 0) {
erts_print(to, to_arg, "Old size: %d\n", modp->old.code_length);
- code = modp->old.code;
- if (code[MI_ATTR_PTR]) {
+ code = modp->old.code_hdr;
+ if (code->attr_ptr) {
erts_print(to, to_arg, "Old attributes: ");
- dump_attributes(to, to_arg, (byte *) code[MI_ATTR_PTR],
- code[MI_ATTR_SIZE]);
+ dump_attributes(to, to_arg, code->attr_ptr,
+ code->attr_size);
}
- if (code[MI_COMPILE_PTR]) {
+ if (code->compile_ptr) {
erts_print(to, to_arg, "Old compilation info: ");
- dump_attributes(to, to_arg, (byte *) code[MI_COMPILE_PTR],
- code[MI_COMPILE_SIZE]);
+ dump_attributes(to, to_arg, code->compile_ptr,
+ code->compile_size);
}
}
}
diff --git a/erts/emulator/beam/copy.c b/erts/emulator/beam/copy.c
index ec769c3b49..67a96f6442 100644
--- a/erts/emulator/beam/copy.c
+++ b/erts/emulator/beam/copy.c
@@ -35,7 +35,7 @@
#include "erl_bits.h"
#include "dtrace-wrapper.h"
-static void move_one_frag(Eterm** hpp, ErlHeapFragment*, ErlOffHeap*);
+static void move_one_frag(Eterm** hpp, ErlHeapFragment*, ErlOffHeap*, int);
/*
* Copy object "obj" to process p.
@@ -75,8 +75,14 @@ Uint size_object(Eterm obj)
Uint sum = 0;
Eterm* ptr;
int arity;
+#ifdef DEBUG
+ Eterm mypid = erts_get_current_pid();
+#endif
DECLARE_ESTACK(s);
+
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] size_object %p\n", mypid, obj));
+
for (;;) {
switch (primary_tag(obj)) {
case TAG_PRIMARY_LIST:
@@ -211,6 +217,7 @@ Uint size_object(Eterm obj)
pop_next:
if (ESTACK_ISEMPTY(s)) {
DESTROY_ESTACK(s);
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] size was: %u\n", mypid, sum));
return sum;
}
obj = ESTACK_POP(s);
@@ -222,9 +229,377 @@ Uint size_object(Eterm obj)
}
/*
+ * Machinery for sharing preserving information
+ * Using a WSTACK but not very transparently; consider refactoring
+ */
+
+#define DECLARE_BITSTORE(s) \
+ DECLARE_WSTACK(s); \
+ int WSTK_CONCAT(s,_bitoffs) = 0; \
+ int WSTK_CONCAT(s,_offset) = 0; \
+ UWord WSTK_CONCAT(s,_buffer) = 0
+
+#define DESTROY_BITSTORE(s) DESTROY_WSTACK(s)
+#define BITSTORE_PUT(s,i) \
+do { \
+ WSTK_CONCAT(s,_buffer) |= i << WSTK_CONCAT(s,_bitoffs); \
+ WSTK_CONCAT(s,_bitoffs) += 2; \
+ if (WSTK_CONCAT(s,_bitoffs) >= 8*sizeof(UWord)) { \
+ WSTACK_PUSH(s, WSTK_CONCAT(s,_buffer)); \
+ WSTK_CONCAT(s,_bitoffs) = 0; \
+ WSTK_CONCAT(s,_buffer) = 0; \
+ } \
+} while(0)
+#define BITSTORE_CLOSE(s) \
+do { \
+ if (WSTK_CONCAT(s,_bitoffs) > 0) { \
+ WSTACK_PUSH(s, WSTK_CONCAT(s,_buffer)); \
+ WSTK_CONCAT(s,_bitoffs) = 0; \
+ } \
+} while(0)
+
+#define BITSTORE_FETCH(s,dst) \
+do { \
+ UWord result; \
+ if (WSTK_CONCAT(s,_bitoffs) <= 0) { \
+ WSTK_CONCAT(s,_buffer) = s.wstart[WSTK_CONCAT(s,_offset)]; \
+ WSTK_CONCAT(s,_offset)++; \
+ WSTK_CONCAT(s,_bitoffs) = 8*sizeof(UWord); \
+ } \
+ WSTK_CONCAT(s,_bitoffs) -= 2; \
+ result = WSTK_CONCAT(s,_buffer) & 3; \
+ WSTK_CONCAT(s,_buffer) >>= 2; \
+ (dst) = result; \
+} while(0)
+
+#define BOXED_VISITED_MASK ((Eterm) 3)
+#define BOXED_VISITED ((Eterm) 1)
+#define BOXED_SHARED_UNPROCESSED ((Eterm) 2)
+#define BOXED_SHARED_PROCESSED ((Eterm) 3)
+
+#define COUNT_OFF_HEAP (0)
+
+#define IN_LITERAL_PURGE_AREA(info, ptr) \
+ ((info)->range_ptr && ( \
+ (info)->range_ptr <= (ptr) && \
+ (ptr) < ((info)->range_ptr + (info)->range_sz)))
+/*
+ * Return the real size of an object and find sharing information
+ * This currently returns the same as erts_debug:size/1.
+ * It is argued whether the size of subterms in constant pools
+ * should be counted or not.
+ */
+
+Uint size_shared(Eterm obj)
+{
+ Eterm saved_obj = obj;
+ Uint sum = 0;
+ Eterm* ptr;
+
+ DECLARE_EQUEUE(s);
+ DECLARE_BITSTORE(b);
+
+ for (;;) {
+ switch (primary_tag(obj)) {
+ case TAG_PRIMARY_LIST: {
+ Eterm head, tail;
+ ptr = list_val(obj);
+ /* we're not counting anything that's outside our heap */
+ if (!COUNT_OFF_HEAP && erts_is_literal(obj,ptr)) {
+ goto pop_next;
+ }
+ head = CAR(ptr);
+ tail = CDR(ptr);
+ /* if it's visited, don't count it */
+ if (primary_tag(tail) == TAG_PRIMARY_HEADER ||
+ primary_tag(head) == TAG_PRIMARY_HEADER) {
+ goto pop_next;
+ }
+ /* else make it visited now */
+ switch (primary_tag(tail)) {
+ case TAG_PRIMARY_LIST:
+ ptr[1] = (tail - TAG_PRIMARY_LIST) | TAG_PRIMARY_HEADER;
+ break;
+ case TAG_PRIMARY_IMMED1:
+ CAR(ptr) = (head - primary_tag(head)) | TAG_PRIMARY_HEADER;
+ CDR(ptr) = (tail - TAG_PRIMARY_IMMED1) | primary_tag(head);
+ break;
+ case TAG_PRIMARY_BOXED:
+ BITSTORE_PUT(b, primary_tag(head));
+ CAR(ptr) = (head - primary_tag(head)) | TAG_PRIMARY_HEADER;
+ CDR(ptr) = (tail - TAG_PRIMARY_BOXED) | TAG_PRIMARY_HEADER;
+ break;
+ }
+ /* and count it */
+ sum += 2;
+ if (!IS_CONST(head)) {
+ EQUEUE_PUT(s, head);
+ }
+ obj = tail;
+ break;
+ }
+ case TAG_PRIMARY_BOXED: {
+ Eterm hdr;
+ ptr = boxed_val(obj);
+ /* we're not counting anything that's outside our heap */
+ if (!COUNT_OFF_HEAP && erts_is_literal(obj,ptr)) {
+ goto pop_next;
+ }
+ hdr = *ptr;
+ /* if it's visited, don't count it */
+ if (primary_tag(hdr) != TAG_PRIMARY_HEADER) {
+ goto pop_next;
+ }
+ /* else make it visited now */
+ *ptr = (hdr - primary_tag(hdr)) + BOXED_VISITED;
+ /* and count it */
+ ASSERT(is_header(hdr));
+ switch (hdr & _TAG_HEADER_MASK) {
+ case ARITYVAL_SUBTAG: {
+ int arity = header_arity(hdr);
+ sum += arity + 1;
+ if (arity == 0) { /* Empty tuple -- unusual. */
+ goto pop_next;
+ }
+ while (arity-- > 0) {
+ obj = *++ptr;
+ if (!IS_CONST(obj)) {
+ EQUEUE_PUT(s, obj);
+ }
+ }
+ goto pop_next;
+ }
+ case FUN_SUBTAG: {
+ ErlFunThing* funp = (ErlFunThing *) ptr;
+ unsigned eterms = 1 /* creator */ + funp->num_free;
+ unsigned sz = thing_arityval(hdr);
+ sum += 1 /* header */ + sz + eterms;
+ ptr += 1 /* header */ + sz;
+ while (eterms-- > 0) {
+ obj = *ptr++;
+ if (!IS_CONST(obj)) {
+ EQUEUE_PUT(s, obj);
+ }
+ }
+ goto pop_next;
+ }
+ case SUB_BINARY_SUBTAG: {
+ ErlSubBin* sb = (ErlSubBin *) ptr;
+ Uint extra_bytes;
+ Eterm hdr;
+ ASSERT((sb->thing_word & ~BOXED_VISITED_MASK) == HEADER_SUB_BIN);
+ if (sb->bitsize + sb->bitoffs > 8) {
+ sum += ERL_SUB_BIN_SIZE;
+ extra_bytes = 2;
+ } else if (sb->bitsize + sb->bitoffs > 0) {
+ sum += ERL_SUB_BIN_SIZE;
+ extra_bytes = 1;
+ } else {
+ extra_bytes = 0;
+ }
+ ptr = binary_val(sb->orig);
+ hdr = (*ptr) & ~BOXED_VISITED_MASK;
+ if (thing_subtag(hdr) == REFC_BINARY_SUBTAG) {
+ sum += PROC_BIN_SIZE;
+ } else {
+ ASSERT(thing_subtag(hdr) == HEAP_BINARY_SUBTAG);
+ sum += heap_bin_size(binary_size(obj) + extra_bytes);
+ }
+ goto pop_next;
+ }
+ case MAP_SUBTAG:
+ switch (MAP_HEADER_TYPE(hdr)) {
+ case MAP_HEADER_TAG_FLATMAP_HEAD : {
+ flatmap_t *mp = (flatmap_t*)flatmap_val(obj);
+ Uint n = flatmap_get_size(mp) + 1;
+ ptr = (Eterm *)mp;
+ sum += n + 2;
+ ptr += 2; /* hdr + size words */
+ while (n--) {
+ obj = *ptr++;
+ if (!IS_CONST(obj)) {
+ EQUEUE_PUT(s, obj);
+ }
+ }
+ goto pop_next;
+ }
+ case MAP_HEADER_TAG_HAMT_HEAD_BITMAP :
+ case MAP_HEADER_TAG_HAMT_HEAD_ARRAY :
+ case MAP_HEADER_TAG_HAMT_NODE_BITMAP : {
+ Uint n = hashmap_bitcount(MAP_HEADER_VAL(hdr));
+ sum += 1 + n + header_arity(hdr);
+ ptr += 1 + header_arity(hdr);
+ while (n--) {
+ obj = *ptr++;
+ if (!IS_CONST(obj)) {
+ EQUEUE_PUT(s, obj);
+ }
+ }
+ goto pop_next;
+ }
+ default:
+ erl_exit(ERTS_ABORT_EXIT, "size_shared: bad hashmap type %d\n", MAP_HEADER_TYPE(hdr));
+ }
+ case BIN_MATCHSTATE_SUBTAG:
+ erl_exit(ERTS_ABORT_EXIT,
+ "size_shared: matchstate term not allowed");
+ default:
+ sum += thing_arityval(hdr) + 1;
+ goto pop_next;
+ }
+ break;
+ }
+ case TAG_PRIMARY_IMMED1:
+ pop_next:
+ if (EQUEUE_ISEMPTY(s)) {
+ goto cleanup;
+ }
+ obj = EQUEUE_GET(s);
+ break;
+ default:
+ erl_exit(ERTS_ABORT_EXIT, "size_shared: bad tag for %#x\n", obj);
+ }
+ }
+
+cleanup:
+ obj = saved_obj;
+ BITSTORE_CLOSE(b);
+ for (;;) {
+ switch (primary_tag(obj)) {
+ case TAG_PRIMARY_LIST: {
+ Eterm head, tail;
+ ptr = list_val(obj);
+ if (!COUNT_OFF_HEAP && erts_is_literal(obj,ptr)) {
+ goto cleanup_next;
+ }
+ head = CAR(ptr);
+ tail = CDR(ptr);
+ /* if not already clean, clean it up */
+ if (primary_tag(tail) == TAG_PRIMARY_HEADER) {
+ if (primary_tag(head) == TAG_PRIMARY_HEADER) {
+ Eterm saved;
+ BITSTORE_FETCH(b, saved);
+ CAR(ptr) = head = (head - TAG_PRIMARY_HEADER) | saved;
+ CDR(ptr) = tail = (tail - TAG_PRIMARY_HEADER) | TAG_PRIMARY_BOXED;
+ } else {
+ CDR(ptr) = tail = (tail - TAG_PRIMARY_HEADER) | TAG_PRIMARY_LIST;
+ }
+ } else if (primary_tag(head) == TAG_PRIMARY_HEADER) {
+ CAR(ptr) = head = (head - TAG_PRIMARY_HEADER) | primary_tag(tail);
+ CDR(ptr) = tail = (tail - primary_tag(tail)) | TAG_PRIMARY_IMMED1;
+ } else {
+ goto cleanup_next;
+ }
+ /* and its children too */
+ if (!IS_CONST(head)) {
+ EQUEUE_PUT_UNCHECKED(s, head);
+ }
+ obj = tail;
+ break;
+ }
+ case TAG_PRIMARY_BOXED: {
+ Eterm hdr;
+ ptr = boxed_val(obj);
+ if (!COUNT_OFF_HEAP && erts_is_literal(obj,ptr)) {
+ goto cleanup_next;
+ }
+ hdr = *ptr;
+ /* if not already clean, clean it up */
+ if (primary_tag(hdr) == TAG_PRIMARY_HEADER) {
+ goto cleanup_next;
+ }
+ else {
+ ASSERT(primary_tag(hdr) == BOXED_VISITED);
+ *ptr = hdr = (hdr - BOXED_VISITED) + TAG_PRIMARY_HEADER;
+ }
+ /* and its children too */
+ switch (hdr & _TAG_HEADER_MASK) {
+ case ARITYVAL_SUBTAG: {
+ int arity = header_arity(hdr);
+ if (arity == 0) { /* Empty tuple -- unusual. */
+ goto cleanup_next;
+ }
+ while (arity-- > 0) {
+ obj = *++ptr;
+ if (!IS_CONST(obj)) {
+ EQUEUE_PUT_UNCHECKED(s, obj);
+ }
+ }
+ goto cleanup_next;
+ }
+ case FUN_SUBTAG: {
+ ErlFunThing* funp = (ErlFunThing *) ptr;
+ unsigned eterms = 1 /* creator */ + funp->num_free;
+ unsigned sz = thing_arityval(hdr);
+ ptr += 1 /* header */ + sz;
+ while (eterms-- > 0) {
+ obj = *ptr++;
+ if (!IS_CONST(obj)) {
+ EQUEUE_PUT_UNCHECKED(s, obj);
+ }
+ }
+ goto cleanup_next;
+ }
+ case MAP_SUBTAG:
+ switch (MAP_HEADER_TYPE(hdr)) {
+ case MAP_HEADER_TAG_FLATMAP_HEAD : {
+ flatmap_t *mp = (flatmap_t *) ptr;
+ Uint n = flatmap_get_size(mp) + 1;
+ ptr += 2; /* hdr + size words */
+ while (n--) {
+ obj = *ptr++;
+ if (!IS_CONST(obj)) {
+ EQUEUE_PUT_UNCHECKED(s, obj);
+ }
+ }
+ goto cleanup_next;
+ }
+ case MAP_HEADER_TAG_HAMT_HEAD_BITMAP :
+ case MAP_HEADER_TAG_HAMT_HEAD_ARRAY :
+ case MAP_HEADER_TAG_HAMT_NODE_BITMAP : {
+ Uint n = hashmap_bitcount(MAP_HEADER_VAL(hdr));
+ sum += 1 + n + header_arity(hdr);
+ ptr += 1 + header_arity(hdr);
+ while (n--) {
+ obj = *ptr++;
+ if (!IS_CONST(obj)) {
+ EQUEUE_PUT_UNCHECKED(s, obj);
+ }
+ }
+ goto cleanup_next;
+ }
+ default:
+ erl_exit(ERTS_ABORT_EXIT, "size_shared: bad hashmap type %d\n", MAP_HEADER_TYPE(hdr));
+ }
+ default:
+ goto cleanup_next;
+ }
+ break;
+ }
+ case TAG_PRIMARY_IMMED1:
+ cleanup_next:
+ if (EQUEUE_ISEMPTY(s)) {
+ goto all_clean;
+ }
+ obj = EQUEUE_GET(s);
+ break;
+ default:
+ erl_exit(ERTS_ABORT_EXIT, "size_shared: bad tag for %#x\n", obj);
+ }
+ }
+
+ all_clean:
+ /* Return the result */
+ DESTROY_EQUEUE(s);
+ DESTROY_BITSTORE(b);
+ return sum;
+}
+
+
+/*
* Copy a structure to a heap.
*/
-Eterm copy_struct(Eterm obj, Uint sz, Eterm** hpp, ErlOffHeap* off_heap)
+Eterm copy_struct_x(Eterm obj, Uint sz, Eterm** hpp, ErlOffHeap* off_heap, Uint *bsz)
{
char* hstart;
Uint hsize;
@@ -239,19 +614,23 @@ Eterm copy_struct(Eterm obj, Uint sz, Eterm** hpp, ErlOffHeap* off_heap)
Eterm* argp;
Eterm* const_tuple;
Eterm hdr;
+ Eterm *hend;
int i;
#ifdef DEBUG
Eterm org_obj = obj;
Uint org_sz = sz;
+ Eterm mypid = erts_get_current_pid();
#endif
if (IS_CONST(obj))
return obj;
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] copy_struct %p\n", mypid, obj));
+
DTRACE1(copy_struct, (int32_t)sz);
hp = htop = *hpp;
- hbot = htop + sz;
+ hbot = hend = htop + sz;
hstart = (char *)htop;
hsize = (char*) hbot - hstart;
const_tuple = 0;
@@ -279,7 +658,7 @@ Eterm copy_struct(Eterm obj, Uint sz, Eterm** hpp, ErlOffHeap* off_heap)
break;
case TAG_PRIMARY_LIST:
objp = list_val(obj);
- if (in_area(objp,hstart,hsize)) {
+ if (ErtsInArea(objp,hstart,hsize)) {
hp++;
break;
}
@@ -318,7 +697,7 @@ Eterm copy_struct(Eterm obj, Uint sz, Eterm** hpp, ErlOffHeap* off_heap)
}
case TAG_PRIMARY_BOXED:
- if (in_area(boxed_val(obj),hstart,hsize)) {
+ if (ErtsInArea(boxed_val(obj),hstart,hsize)) {
hp++;
break;
}
@@ -516,22 +895,870 @@ Eterm copy_struct(Eterm obj, Uint sz, Eterm** hpp, ErlOffHeap* off_heap)
}
}
+ if (bsz) {
+ *hpp = htop;
+ *bsz = hend - hbot;
+ } else {
#ifdef DEBUG
- if (htop != hbot)
- erl_exit(ERTS_ABORT_EXIT,
- "Internal error in copy_struct() when copying %T:"
- " htop=%p != hbot=%p (sz=%beu)\n",
- org_obj, htop, hbot, org_sz);
+ if (htop != hbot)
+ erl_exit(ERTS_ABORT_EXIT,
+ "Internal error in copy_struct() when copying %T:"
+ " htop=%p != hbot=%p (sz=%beu)\n",
+ org_obj, htop, hbot, org_sz);
#else
- if (htop > hbot) {
- erl_exit(ERTS_ABORT_EXIT,
- "Internal error in copy_struct(): htop, hbot overrun\n");
- }
+ if (htop > hbot) {
+ erl_exit(ERTS_ABORT_EXIT,
+ "Internal error in copy_struct(): htop, hbot overrun\n");
+ }
#endif
- *hpp = (Eterm *) (hstart+hsize);
+ *hpp = (Eterm *) (hstart+hsize);
+ }
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] result is at %p\n", mypid, res));
return res;
}
+
+/*
+ * Machinery for the table used by the sharing preserving copier
+ * Using an ESTACK but not very transparently; consider refactoring
+ */
+
+#define DECLARE_SHTABLE(s) \
+ DECLARE_ESTACK(s); \
+ Uint ESTK_CONCAT(s,_offset) = 0
+#define DESTROY_SHTABLE(s) DESTROY_ESTACK(s)
+#define SHTABLE_INCR 4
+#define SHTABLE_NEXT(s) ESTK_CONCAT(s,_offset)
+#define SHTABLE_PUSH(s,x,y,b) \
+do { \
+ if (s.sp > s.end - SHTABLE_INCR) { \
+ erl_grow_estack(&(s), SHTABLE_INCR); \
+ } \
+ *s.sp++ = (x); \
+ *s.sp++ = (y); \
+ *s.sp++ = (Eterm) NULL; \
+ *s.sp++ = (Eterm) (b); \
+ ESTK_CONCAT(s,_offset) += SHTABLE_INCR; \
+} while(0)
+#define SHTABLE_X(s,e) (s.start[e])
+#define SHTABLE_Y(s,e) (s.start[(e)+1])
+#define SHTABLE_FWD(s,e) ((Eterm *) (s.start[(e)+2]))
+#define SHTABLE_FWD_UPD(s,e,p) (s.start[(e)+2] = (Eterm) (p))
+#define SHTABLE_REV(s,e) ((Eterm *) (s.start[(e)+3]))
+
+#define LIST_SHARED_UNPROCESSED ((Eterm) 0)
+#define LIST_SHARED_PROCESSED ((Eterm) 1)
+
+#define HEAP_ELEM_TO_BE_FILLED _unchecked_make_list(NULL)
+
+
+/*
+ * Specialized macros for using/reusing the persistent state
+ */
+
+#define DECLARE_EQUEUE_INIT_INFO(q, info) \
+ UWord* EQUE_DEF_QUEUE(q) = info->queue_default; \
+ ErtsEQueue q = { \
+ EQUE_DEF_QUEUE(q), /* start */ \
+ EQUE_DEF_QUEUE(q), /* front */ \
+ EQUE_DEF_QUEUE(q), /* back */ \
+ 1, /* possibly_empty */ \
+ EQUE_DEF_QUEUE(q) + DEF_EQUEUE_SIZE, /* end */ \
+ ERTS_ALC_T_ESTACK /* alloc_type */ \
+ }
+
+#define DECLARE_EQUEUE_FROM_INFO(q, info) \
+ /* no EQUE_DEF_QUEUE(q), read-only */ \
+ ErtsEQueue q = { \
+ info->queue_start, /* start */ \
+ info->queue_start, /* front */ \
+ info->queue_start, /* back */ \
+ 1, /* possibly_empty */ \
+ info->queue_end, /* end */ \
+ info->queue_alloc_type /* alloc_type */ \
+ }
+
+#define DECLARE_BITSTORE_INIT_INFO(s, info) \
+ UWord* WSTK_DEF_STACK(s) = info->bitstore_default; \
+ ErtsWStack s = { \
+ WSTK_DEF_STACK(s), /* wstart */ \
+ WSTK_DEF_STACK(s), /* wsp */ \
+ WSTK_DEF_STACK(s) + DEF_WSTACK_SIZE, /* wend */ \
+ WSTK_DEF_STACK(s), /* wdflt */ \
+ ERTS_ALC_T_ESTACK /* alloc_type */ \
+ }; \
+ int WSTK_CONCAT(s,_bitoffs) = 0; \
+ /* no WSTK_CONCAT(s,_offset), write-only */ \
+ UWord WSTK_CONCAT(s,_buffer) = 0
+
+#define DECLARE_BITSTORE_FROM_INFO(s, info) \
+ /* no WSTK_DEF_STACK(s), read-only */ \
+ ErtsWStack s = { \
+ info->bitstore_start, /* wstart */ \
+ NULL, /* wsp, read-only */ \
+ NULL, /* wend, read-only */ \
+ NULL, /* wdef, read-only */ \
+ info->bitstore_alloc_type /* alloc_type */ \
+ }; \
+ int WSTK_CONCAT(s,_bitoffs) = 0; \
+ int WSTK_CONCAT(s,_offset) = 0; \
+ UWord WSTK_CONCAT(s,_buffer) = 0
+
+#define DECLARE_SHTABLE_INIT_INFO(s, info) \
+ Eterm* ESTK_DEF_STACK(s) = info->shtable_default; \
+ ErtsEStack s = { \
+ ESTK_DEF_STACK(s), /* start */ \
+ ESTK_DEF_STACK(s), /* sp */ \
+ ESTK_DEF_STACK(s) + DEF_ESTACK_SIZE, /* end */ \
+ ESTK_DEF_STACK(s), /* default */ \
+ ERTS_ALC_T_ESTACK /* alloc_type */ \
+ }; \
+ Uint ESTK_CONCAT(s,_offset) = 0
+
+#define DECLARE_SHTABLE_FROM_INFO(s, info) \
+ /* no ESTK_DEF_STACK(s), read-only */ \
+ ErtsEStack s = { \
+ info->shtable_start, /* start */ \
+ NULL, /* sp, read-only */ \
+ NULL, /* end, read-only */ \
+ NULL, /* def, read-only */ \
+ info->shtable_alloc_type /* alloc_type */ \
+ }; \
+ /* no ESTK_CONCAT(s,_offset), read-only */
+
+/*
+ * Copy object "obj" preserving sharing.
+ * First half: count size and calculate sharing.
+ */
+Uint copy_shared_calculate(Eterm obj, erts_shcopy_t *info)
+{
+ Uint sum;
+ Uint e;
+ unsigned sz;
+ Eterm* ptr;
+#ifdef DEBUG
+ Eterm mypid = erts_get_current_pid();
+#endif
+
+ DECLARE_EQUEUE_INIT_INFO(s, info);
+ DECLARE_BITSTORE_INIT_INFO(b, info);
+ DECLARE_SHTABLE_INIT_INFO(t, info);
+
+ /* step #0:
+ -------------------------------------------------------
+ get rid of the easy cases first:
+ - copying constants
+ - if not a proper process, do flat copy
+ */
+
+ if (IS_CONST(obj))
+ return 0;
+
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] copy_shared_calculate %p\n", mypid, obj));
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] message is %T\n", mypid, obj));
+
+ /* step #1:
+ -------------------------------------------------------
+ traverse the term and calculate the size;
+ when traversing, transform as you do in size_shared
+ but when you find shared objects:
+
+ a. add entry in the table, indexed by i
+ b. mark them:
+ b1. boxed terms, set header to (i | 11)
+ store (old header, NONV, NULL, backptr) in the entry
+ b2. cons cells, set CDR to NONV, set CAR to i
+ store (old CAR, old CDR, NULL, backptr) in the entry
+ */
+
+ sum = 0;
+
+ for (;;) {
+ switch (primary_tag(obj)) {
+ case TAG_PRIMARY_LIST: {
+ Eterm head, tail;
+ ptr = list_val(obj);
+ /* off heap list pointers are copied verbatim */
+ if (erts_is_literal(obj,ptr)) {
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] bypassed copying %p is %T\n", mypid, ptr, obj));
+ if (IN_LITERAL_PURGE_AREA(info,ptr))
+ info->literal_size += size_object(obj);
+ goto pop_next;
+ }
+ head = CAR(ptr);
+ tail = CDR(ptr);
+ /* if it's visited, don't count it;
+ if not already shared, make it shared and store it in the table */
+ if (primary_tag(tail) == TAG_PRIMARY_HEADER ||
+ primary_tag(head) == TAG_PRIMARY_HEADER) {
+ if (tail != THE_NON_VALUE) {
+ e = SHTABLE_NEXT(t);
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] tabling L %p\n", mypid, ptr));
+ SHTABLE_PUSH(t, head, tail, ptr);
+ CAR(ptr) = (e << _TAG_PRIMARY_SIZE) | LIST_SHARED_UNPROCESSED;
+ CDR(ptr) = THE_NON_VALUE;
+ }
+ goto pop_next;
+ }
+ /* else make it visited now */
+ switch (primary_tag(tail)) {
+ case TAG_PRIMARY_LIST:
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] mangling L/L %p\n", mypid, ptr));
+ CDR(ptr) = (tail - TAG_PRIMARY_LIST) | TAG_PRIMARY_HEADER;
+ break;
+ case TAG_PRIMARY_IMMED1:
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] mangling L/I %p\n", mypid, ptr));
+ CAR(ptr) = (head - primary_tag(head)) | TAG_PRIMARY_HEADER;
+ CDR(ptr) = (tail - TAG_PRIMARY_IMMED1) | primary_tag(head);
+ break;
+ case TAG_PRIMARY_BOXED:
+ BITSTORE_PUT(b, primary_tag(head));
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] mangling L/B %p\n", mypid, ptr));
+ CAR(ptr) = (head - primary_tag(head)) | TAG_PRIMARY_HEADER;
+ CDR(ptr) = (tail - TAG_PRIMARY_BOXED) | TAG_PRIMARY_HEADER;
+ break;
+ }
+ /* and count it */
+ sum += 2;
+ if (!IS_CONST(head)) {
+ EQUEUE_PUT(s, head);
+ }
+ obj = tail;
+ break;
+ }
+ case TAG_PRIMARY_BOXED: {
+ Eterm hdr;
+ ptr = boxed_val(obj);
+ /* off heap pointers to boxes are copied verbatim */
+ if (erts_is_literal(obj,ptr)) {
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] bypassed copying %p is %T\n", mypid, ptr, obj));
+ if (IN_LITERAL_PURGE_AREA(info,ptr))
+ info->literal_size += size_object(obj);
+ goto pop_next;
+ }
+ hdr = *ptr;
+ /* if it's visited, don't count it;
+ if not already shared, make it shared and store it in the table */
+ if (primary_tag(hdr) != TAG_PRIMARY_HEADER) {
+ if (primary_tag(hdr) == BOXED_VISITED) {
+ e = SHTABLE_NEXT(t);
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] tabling B %p\n", mypid, ptr));
+ SHTABLE_PUSH(t, hdr, THE_NON_VALUE, ptr);
+ *ptr = (e << _TAG_PRIMARY_SIZE) | BOXED_SHARED_UNPROCESSED;
+ }
+ goto pop_next;
+ }
+ /* else make it visited now */
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] mangling B %p\n", mypid, ptr));
+ *ptr = (hdr - primary_tag(hdr)) + BOXED_VISITED;
+ /* and count it */
+ ASSERT(is_header(hdr));
+ switch (hdr & _TAG_HEADER_MASK) {
+ case ARITYVAL_SUBTAG: {
+ int arity = header_arity(hdr);
+ sum += arity + 1;
+ if (arity == 0) { /* Empty tuple -- unusual. */
+ goto pop_next;
+ }
+ while (arity-- > 0) {
+ obj = *++ptr;
+ if (!IS_CONST(obj)) {
+ EQUEUE_PUT(s, obj);
+ }
+ }
+ goto pop_next;
+ }
+ case FUN_SUBTAG: {
+ ErlFunThing* funp = (ErlFunThing *) ptr;
+ unsigned eterms = 1 /* creator */ + funp->num_free;
+ sz = thing_arityval(hdr);
+ sum += 1 /* header */ + sz + eterms;
+ ptr += 1 /* header */ + sz;
+ while (eterms-- > 0) {
+ obj = *ptr++;
+ if (!IS_CONST(obj)) {
+ EQUEUE_PUT(s, obj);
+ }
+ }
+ goto pop_next;
+ }
+ case SUB_BINARY_SUBTAG: {
+ ErlSubBin* sb = (ErlSubBin *) ptr;
+ Eterm real_bin = sb->orig;
+ Uint bit_offset = sb->bitoffs;
+ Uint bit_size = sb->bitsize;
+ size_t size = sb->size;
+ Uint extra_bytes;
+ Eterm hdr;
+ if (bit_size + bit_offset > 8) {
+ sum += ERL_SUB_BIN_SIZE;
+ extra_bytes = 2;
+ } else if (bit_size + bit_offset > 0) {
+ sum += ERL_SUB_BIN_SIZE;
+ extra_bytes = 1;
+ } else {
+ extra_bytes = 0;
+ }
+ ASSERT(is_boxed(real_bin) &&
+ (((*boxed_val(real_bin)) &
+ (_TAG_HEADER_MASK - _BINARY_XXX_MASK - BOXED_VISITED_MASK))
+ == _TAG_HEADER_REFC_BIN));
+ hdr = *_unchecked_binary_val(real_bin) & ~BOXED_VISITED_MASK;
+ if (thing_subtag(hdr) == HEAP_BINARY_SUBTAG) {
+ sum += heap_bin_size(size+extra_bytes);
+ } else {
+ ASSERT(thing_subtag(hdr) == REFC_BINARY_SUBTAG);
+ sum += PROC_BIN_SIZE;
+ }
+ goto pop_next;
+ }
+ case MAP_SUBTAG:
+ switch (MAP_HEADER_TYPE(hdr)) {
+ case MAP_HEADER_TAG_FLATMAP_HEAD : {
+ flatmap_t *mp = (flatmap_t *) ptr;
+ Uint n = flatmap_get_size(mp) + 1;
+ sum += n + 2;
+ ptr += 2; /* hdr + size words */
+ while (n--) {
+ obj = *ptr++;
+ if (!IS_CONST(obj)) {
+ EQUEUE_PUT(s, obj);
+ }
+ }
+ goto pop_next;
+ }
+ case MAP_HEADER_TAG_HAMT_HEAD_BITMAP :
+ case MAP_HEADER_TAG_HAMT_HEAD_ARRAY :
+ case MAP_HEADER_TAG_HAMT_NODE_BITMAP : {
+ Uint n = hashmap_bitcount(MAP_HEADER_VAL(hdr));
+ sum += 1 + n + header_arity(hdr);
+ ptr += 1 + header_arity(hdr);
+
+ if (n == 0) {
+ goto pop_next;
+ }
+ while(n--) {
+ obj = *ptr++;
+ if (!IS_CONST(obj)) {
+ EQUEUE_PUT(s, obj);
+ }
+ }
+ goto pop_next;
+ }
+ default:
+ erl_exit(ERTS_ABORT_EXIT, "copy_shared_calculate: bad hashmap type %d\n", MAP_HEADER_TYPE(hdr));
+ }
+ case BIN_MATCHSTATE_SUBTAG:
+ erl_exit(ERTS_ABORT_EXIT,
+ "size_shared: matchstate term not allowed");
+ default:
+ sum += thing_arityval(hdr) + 1;
+ goto pop_next;
+ }
+ break;
+ }
+ case TAG_PRIMARY_IMMED1:
+ pop_next:
+ if (EQUEUE_ISEMPTY(s)) {
+ /* add sentinel to the table */
+ SHTABLE_PUSH(t, THE_NON_VALUE, THE_NON_VALUE, NULL);
+ /* store persistent info */
+ BITSTORE_CLOSE(b);
+ info->queue_start = s.start;
+ info->queue_end = s.end;
+ info->queue_alloc_type = s.alloc_type;
+ info->bitstore_start = b.wstart;
+ info->bitstore_alloc_type = b.alloc_type;
+ info->shtable_start = t.start;
+ info->shtable_alloc_type = t.alloc_type;
+ /* single point of return: the size of the object */
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] size was: %u\n", mypid, sum));
+ return sum + info->literal_size;
+ }
+ obj = EQUEUE_GET(s);
+ break;
+ default:
+ erl_exit(ERTS_ABORT_EXIT, "[pid=%T] size_shared: bad tag for %#x\n", obj);
+ }
+ }
+}
+
+/*
+ * Copy object "obj" preserving sharing.
+ * Second half: copy and restore the object.
+ */
+Uint copy_shared_perform(Eterm obj, Uint size, erts_shcopy_t *info,
+ Eterm** hpp, ErlOffHeap* off_heap) {
+ Uint e;
+ unsigned sz;
+ Eterm* ptr;
+ Eterm* hp;
+ Eterm* hscan;
+ Eterm result;
+ Eterm* resp;
+ Eterm *hbot, *hend;
+ unsigned remaining;
+#ifdef DEBUG
+ Eterm mypid = erts_get_current_pid();
+ Eterm saved_obj = obj;
+#endif
+
+ DECLARE_EQUEUE_FROM_INFO(s, info);
+ DECLARE_BITSTORE_FROM_INFO(b, info);
+ DECLARE_SHTABLE_FROM_INFO(t, info);
+
+ /* step #0:
+ -------------------------------------------------------
+ get rid of the easy cases first:
+ - copying constants
+ - if not a proper process, do flat copy
+ */
+
+ if (IS_CONST(obj))
+ return obj;
+
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] copy_shared_perform %p\n", mypid, obj));
+
+ /* step #2: was performed before this function was called
+ -------------------------------------------------------
+ allocate new space
+ */
+
+ hscan = hp = *hpp;
+ hbot = hend = hp + size;
+
+ /* step #3:
+ -------------------------------------------------------
+ traverse the term a second time and when traversing:
+ a. if the object is marked as shared
+ a1. if the entry contains a forwarding ptr, use that
+ a2. otherwise, copy it to the new space and store the
+ forwarding ptr to the entry
+ b. otherwise, reverse-transform as you do in size_shared
+ and copy to the new space
+ */
+
+ resp = &result;
+ remaining = 0;
+ for (;;) {
+ switch (primary_tag(obj)) {
+ case TAG_PRIMARY_LIST: {
+ Eterm head, tail;
+ ptr = list_val(obj);
+ /* off heap list pointers are copied verbatim */
+ if (erts_is_literal(obj,ptr)) {
+ if (!IN_LITERAL_PURGE_AREA(info,ptr)) {
+ *resp = obj;
+ } else {
+ Uint bsz = 0;
+ *resp = copy_struct_x(obj, hbot - hp, &hp, off_heap, &bsz);
+ hbot -= bsz;
+ }
+ goto cleanup_next;
+ }
+ head = CAR(ptr);
+ tail = CDR(ptr);
+ /* if it is shared */
+ if (tail == THE_NON_VALUE) {
+ e = head >> _TAG_PRIMARY_SIZE;
+ /* if it has been processed, just use the forwarding pointer */
+ if (primary_tag(head) == LIST_SHARED_PROCESSED) {
+ *resp = make_list(SHTABLE_FWD(t, e));
+ goto cleanup_next;
+ }
+ /* else, let's process it now,
+ copy it and keep the forwarding pointer */
+ else {
+ CAR(ptr) = (head - primary_tag(head)) + LIST_SHARED_PROCESSED;
+ head = SHTABLE_X(t, e);
+ tail = SHTABLE_Y(t, e);
+ ptr = &(SHTABLE_X(t, e));
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] tabled L %p is %p\n", mypid, ptr, SHTABLE_REV(t, e)));
+ SHTABLE_FWD_UPD(t, e, hp);
+ }
+ }
+ /* if not already clean, clean it up and copy it */
+ if (primary_tag(tail) == TAG_PRIMARY_HEADER) {
+ if (primary_tag(head) == TAG_PRIMARY_HEADER) {
+ Eterm saved;
+ BITSTORE_FETCH(b, saved);
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] unmangling L/B %p\n", mypid, ptr));
+ CAR(ptr) = head = (head - TAG_PRIMARY_HEADER) + saved;
+ CDR(ptr) = tail = (tail - TAG_PRIMARY_HEADER) + TAG_PRIMARY_BOXED;
+ } else {
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] unmangling L/L %p\n", mypid, ptr));
+ CDR(ptr) = tail = (tail - TAG_PRIMARY_HEADER) + TAG_PRIMARY_LIST;
+ }
+ } else if (primary_tag(head) == TAG_PRIMARY_HEADER) {
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] unmangling L/I %p\n", mypid, ptr));
+ CAR(ptr) = head = (head - TAG_PRIMARY_HEADER) | primary_tag(tail);
+ CDR(ptr) = tail = (tail - primary_tag(tail)) | TAG_PRIMARY_IMMED1;
+ } else {
+ ASSERT(0 && "cannot come here");
+ goto cleanup_next;
+ }
+ /* and its children too */
+ if (IS_CONST(head)) {
+ CAR(hp) = head;
+ } else {
+ EQUEUE_PUT_UNCHECKED(s, head);
+ CAR(hp) = HEAP_ELEM_TO_BE_FILLED;
+ }
+ *resp = make_list(hp);
+ resp = &(CDR(hp));
+ hp += 2;
+ obj = tail;
+ break;
+ }
+ case TAG_PRIMARY_BOXED: {
+ Eterm hdr;
+ ptr = boxed_val(obj);
+ /* off heap pointers to boxes are copied verbatim */
+ if (erts_is_literal(obj,ptr)) {
+ if (!IN_LITERAL_PURGE_AREA(info,ptr)) {
+ *resp = obj;
+ } else {
+ Uint bsz = 0;
+ *resp = copy_struct_x(obj, hbot - hp, &hp, off_heap, &bsz);
+ hbot -= bsz;
+ }
+ goto cleanup_next;
+ }
+ hdr = *ptr;
+ /* clean it up, unless it's already clean or shared and processed */
+ switch (primary_tag(hdr)) {
+ case TAG_PRIMARY_HEADER:
+ ASSERT(0 && "cannot come here");
+ /* if it is shared and has been processed,
+ just use the forwarding pointer */
+ case BOXED_SHARED_PROCESSED:
+ e = hdr >> _TAG_PRIMARY_SIZE;
+ *resp = make_boxed(SHTABLE_FWD(t, e));
+ goto cleanup_next;
+ /* if it is shared but has not been processed yet, let's process
+ it now: copy it and keep the forwarding pointer */
+ case BOXED_SHARED_UNPROCESSED:
+ e = hdr >> _TAG_PRIMARY_SIZE;
+ *ptr = (hdr - primary_tag(hdr)) + BOXED_SHARED_PROCESSED;
+ hdr = SHTABLE_X(t, e);
+ ASSERT(primary_tag(hdr) == BOXED_VISITED);
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] tabled B %p is %p\n", mypid, ptr, SHTABLE_REV(t, e)));
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] unmangling B %p\n", mypid, ptr));
+ SHTABLE_X(t, e) = hdr = (hdr - BOXED_VISITED) + TAG_PRIMARY_HEADER;
+ SHTABLE_FWD_UPD(t, e, hp);
+ break;
+ case BOXED_VISITED:
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] unmangling B %p\n", mypid, ptr));
+ *ptr = hdr = (hdr - BOXED_VISITED) + TAG_PRIMARY_HEADER;
+ break;
+ }
+ /* and its children too */
+ switch (hdr & _TAG_HEADER_MASK) {
+ case ARITYVAL_SUBTAG: {
+ int arity = header_arity(hdr);
+ *resp = make_boxed(hp);
+ *hp++ = hdr;
+ while (arity-- > 0) {
+ obj = *++ptr;
+ if (IS_CONST(obj)) {
+ *hp++ = obj;
+ } else {
+ EQUEUE_PUT_UNCHECKED(s, obj);
+ *hp++ = HEAP_ELEM_TO_BE_FILLED;
+ }
+ }
+ goto cleanup_next;
+ }
+ case FUN_SUBTAG: {
+ ErlFunThing* funp = (ErlFunThing *) ptr;
+ unsigned eterms = 1 /* creator */ + funp->num_free;
+ sz = thing_arityval(hdr);
+ funp = (ErlFunThing *) hp;
+ *resp = make_fun(hp);
+ *hp++ = hdr;
+ ptr++;
+ while (sz-- > 0) {
+ *hp++ = *ptr++;
+ }
+ while (eterms-- > 0) {
+ obj = *ptr++;
+ if (IS_CONST(obj)) {
+ *hp++ = obj;
+ } else {
+ EQUEUE_PUT_UNCHECKED(s, obj);
+ *hp++ = HEAP_ELEM_TO_BE_FILLED;
+ }
+ }
+ funp->next = off_heap->first;
+ off_heap->first = (struct erl_off_heap_header*) funp;
+ erts_refc_inc(&funp->fe->refc, 2);
+ goto cleanup_next;
+ }
+ case MAP_SUBTAG:
+ *resp = make_flatmap(hp);
+ *hp++ = hdr;
+ switch (MAP_HEADER_TYPE(hdr)) {
+ case MAP_HEADER_TAG_FLATMAP_HEAD : {
+ flatmap_t *mp = (flatmap_t *) ptr;
+ Uint n = flatmap_get_size(mp) + 1;
+ *hp++ = *++ptr; /* keys */
+ while (n--) {
+ obj = *++ptr;
+ if (IS_CONST(obj)) {
+ *hp++ = obj;
+ } else {
+ EQUEUE_PUT_UNCHECKED(s, obj);
+ *hp++ = HEAP_ELEM_TO_BE_FILLED;
+ }
+ }
+ goto cleanup_next;
+ }
+ case MAP_HEADER_TAG_HAMT_HEAD_BITMAP :
+ case MAP_HEADER_TAG_HAMT_HEAD_ARRAY :
+ *hp++ = *++ptr; /* total map size */
+ case MAP_HEADER_TAG_HAMT_NODE_BITMAP : {
+ Uint n = hashmap_bitcount(MAP_HEADER_VAL(hdr));
+ while (n--) {
+ obj = *++ptr;
+ if (IS_CONST(obj)) {
+ *hp++ = obj;
+ } else {
+ EQUEUE_PUT_UNCHECKED(s, obj);
+ *hp++ = HEAP_ELEM_TO_BE_FILLED;
+ }
+ }
+ goto cleanup_next;
+ }
+ default:
+ erl_exit(ERTS_ABORT_EXIT, "copy_shared_perform: bad hashmap type %d\n", MAP_HEADER_TYPE(hdr));
+ }
+ case REFC_BINARY_SUBTAG: {
+ ProcBin* pb = (ProcBin *) ptr;
+ sz = thing_arityval(hdr);
+ if (pb->flags) {
+ erts_emasculate_writable_binary(pb);
+ }
+ pb = (ProcBin *) hp;
+ *resp = make_binary(hp);
+ *hp++ = hdr;
+ ptr++;
+ while (sz-- > 0) {
+ *hp++ = *ptr++;
+ }
+ erts_refc_inc(&pb->val->refc, 2);
+ pb->next = off_heap->first;
+ pb->flags = 0;
+ off_heap->first = (struct erl_off_heap_header*) pb;
+ OH_OVERHEAD(off_heap, pb->size / sizeof(Eterm));
+ goto cleanup_next;
+ }
+ case SUB_BINARY_SUBTAG: {
+ ErlSubBin* sb = (ErlSubBin *) ptr;
+ Eterm real_bin = sb->orig;
+ Uint bit_offset = sb->bitoffs;
+ Uint bit_size = sb->bitsize;
+ Uint offset = sb->offs;
+ size_t size = sb->size;
+ Uint extra_bytes;
+ Uint real_size;
+ if ((bit_size + bit_offset) > 8) {
+ extra_bytes = 2;
+ } else if ((bit_size + bit_offset) > 0) {
+ extra_bytes = 1;
+ } else {
+ extra_bytes = 0;
+ }
+ real_size = size+extra_bytes;
+ ASSERT(is_boxed(real_bin) &&
+ (((*boxed_val(real_bin)) &
+ (_TAG_HEADER_MASK - _BINARY_XXX_MASK - BOXED_VISITED_MASK))
+ == _TAG_HEADER_REFC_BIN));
+ ptr = _unchecked_binary_val(real_bin);
+ *resp = make_binary(hp);
+ if (extra_bytes != 0) {
+ ErlSubBin* res = (ErlSubBin *) hp;
+ hp += ERL_SUB_BIN_SIZE;
+ res->thing_word = HEADER_SUB_BIN;
+ res->size = size;
+ res->bitsize = bit_size;
+ res->bitoffs = bit_offset;
+ res->offs = 0;
+ res->is_writable = 0;
+ res->orig = make_binary(hp);
+ }
+ if (thing_subtag(*ptr & ~BOXED_VISITED_MASK) == HEAP_BINARY_SUBTAG) {
+ ErlHeapBin* from = (ErlHeapBin *) ptr;
+ ErlHeapBin* to = (ErlHeapBin *) hp;
+ hp += heap_bin_size(real_size);
+ to->thing_word = header_heap_bin(real_size);
+ to->size = real_size;
+ sys_memcpy(to->data, ((byte *)from->data)+offset, real_size);
+ } else {
+ ProcBin* from = (ProcBin *) ptr;
+ ProcBin* to = (ProcBin *) hp;
+ ASSERT(thing_subtag(*ptr & ~BOXED_VISITED_MASK) == REFC_BINARY_SUBTAG);
+ if (from->flags) {
+ erts_emasculate_writable_binary(from);
+ }
+ hp += PROC_BIN_SIZE;
+ to->thing_word = HEADER_PROC_BIN;
+ to->size = real_size;
+ to->val = from->val;
+ erts_refc_inc(&to->val->refc, 2);
+ to->bytes = from->bytes + offset;
+ to->next = off_heap->first;
+ to->flags = 0;
+ off_heap->first = (struct erl_off_heap_header*) to;
+ OH_OVERHEAD(off_heap, to->size / sizeof(Eterm));
+ }
+ goto cleanup_next;
+ }
+ case EXTERNAL_PID_SUBTAG:
+ case EXTERNAL_PORT_SUBTAG:
+ case EXTERNAL_REF_SUBTAG: {
+ ExternalThing *etp = (ExternalThing *) hp;
+ sz = thing_arityval(hdr);
+ *resp = make_external(hp);
+ *hp++ = hdr;
+ ptr++;
+ while (sz-- > 0) {
+ *hp++ = *ptr++;
+ }
+ etp->next = off_heap->first;
+ off_heap->first = (struct erl_off_heap_header*) etp;
+ erts_refc_inc(&etp->node->refc, 2);
+ goto cleanup_next;
+ }
+ default:
+ sz = thing_arityval(hdr);
+ *resp = make_boxed(hp);
+ *hp++ = hdr;
+ ptr++;
+ while (sz-- > 0) {
+ *hp++ = *ptr++;
+ }
+ goto cleanup_next;
+ }
+ break;
+ }
+ case TAG_PRIMARY_IMMED1:
+ *resp = obj;
+ cleanup_next:
+ if (EQUEUE_ISEMPTY(s)) {
+ goto all_clean;
+ }
+ obj = EQUEUE_GET(s);
+ for (;;) {
+ ASSERT(hscan < hp);
+ if (remaining == 0) {
+ if (*hscan == HEAP_ELEM_TO_BE_FILLED) {
+ resp = hscan;
+ hscan += 2;
+ break; /* scanning loop */
+ } else if (primary_tag(*hscan) == TAG_PRIMARY_HEADER) {
+ switch (*hscan & _TAG_HEADER_MASK) {
+ case ARITYVAL_SUBTAG:
+ remaining = header_arity(*hscan);
+ hscan++;
+ break;
+ case FUN_SUBTAG: {
+ ErlFunThing* funp = (ErlFunThing *) hscan;
+ hscan += 1 + thing_arityval(*hscan);
+ remaining = 1 + funp->num_free;
+ break;
+ }
+ case MAP_SUBTAG:
+ switch (MAP_HEADER_TYPE(*hscan)) {
+ case MAP_HEADER_TAG_FLATMAP_HEAD : {
+ flatmap_t *mp = (flatmap_t *) hscan;
+ remaining = flatmap_get_size(mp) + 1;
+ hscan += 2;
+ break;
+ }
+ case MAP_HEADER_TAG_HAMT_HEAD_BITMAP :
+ case MAP_HEADER_TAG_HAMT_HEAD_ARRAY :
+ case MAP_HEADER_TAG_HAMT_NODE_BITMAP :
+ remaining = hashmap_bitcount(MAP_HEADER_VAL(*hscan));
+ hscan += MAP_HEADER_ARITY(*hscan) + 1;
+ break;
+ default:
+ erl_exit(ERTS_ABORT_EXIT,
+ "copy_shared_perform: bad hashmap type %d\n",
+ MAP_HEADER_TYPE(*hscan));
+ }
+ break;
+ case SUB_BINARY_SUBTAG:
+ ASSERT(((ErlSubBin *) hscan)->bitoffs +
+ ((ErlSubBin *) hscan)->bitsize > 0);
+ hscan += ERL_SUB_BIN_SIZE;
+ break;
+ default:
+ hscan += 1 + thing_arityval(*hscan);
+ break;
+ }
+ } else {
+ hscan++;
+ }
+ } else if (*hscan == HEAP_ELEM_TO_BE_FILLED) {
+ resp = hscan++;
+ remaining--;
+ break; /* scanning loop */
+ } else {
+ hscan++;
+ remaining--;
+ }
+ }
+ ASSERT(resp < hp);
+ break;
+ default:
+ erl_exit(ERTS_ABORT_EXIT, "size_shared: bad tag for %#x\n", obj);
+ }
+ }
+
+ /* step #4:
+ -------------------------------------------------------
+ traverse the table and reverse-transform all stored entries
+ */
+
+all_clean:
+ for (e = 0; ; e += SHTABLE_INCR) {
+ ptr = SHTABLE_REV(t, e);
+ if (ptr == NULL)
+ break;
+ VERBOSE(DEBUG_SHCOPY, ("[copy] restoring shared: %x\n", ptr));
+ /* entry was a list */
+ if (SHTABLE_Y(t, e) != THE_NON_VALUE) {
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] untabling L %p\n", mypid, ptr));
+ CAR(ptr) = SHTABLE_X(t, e);
+ CDR(ptr) = SHTABLE_Y(t, e);
+ }
+ /* entry was boxed */
+ else {
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] untabling B %p\n", mypid, ptr));
+ *ptr = SHTABLE_X(t, e);
+ ASSERT(primary_tag(*ptr) == TAG_PRIMARY_HEADER);
+ }
+ }
+
+#ifdef DEBUG
+ if (eq(saved_obj, result) == 0) {
+ erts_fprintf(stderr, "original = %T\n", saved_obj);
+ erts_fprintf(stderr, "copy = %T\n", result);
+ erl_exit(ERTS_ABORT_EXIT, "copy (shared) not equal to source\n");
+ }
+#endif
+
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] original was %T\n", mypid, saved_obj));
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] copy is %T\n", mypid, result));
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] result is at %p\n", mypid, result));
+
+ ASSERT(hbot == hp);
+ ASSERT(size == ((hp - *hpp) + (hend - hbot)));
+ *hpp = hend;
+ return result;
+}
+
+
/*
* Copy a term that is guaranteed to be contained in a single
* heap block. The heap block is copied word by word, and any
@@ -621,17 +1848,24 @@ Eterm copy_shallow(Eterm* ptr, Uint sz, Eterm** hpp, ErlOffHeap* off_heap)
* move markers.
* Typically used to copy a multi-fragmented message (from NIF).
*/
-void move_multi_frags(Eterm** hpp, ErlOffHeap* off_heap, ErlHeapFragment* first,
- Eterm* refs, unsigned nrefs)
+void erts_move_multi_frags(Eterm** hpp, ErlOffHeap* off_heap, ErlHeapFragment* first,
+ Eterm* refs, unsigned nrefs, int literals)
{
ErlHeapFragment* bp;
Eterm* hp_start = *hpp;
Eterm* hp_end;
Eterm* hp;
unsigned i;
+ Eterm literal_tag;
+
+#ifdef TAG_LITERAL_PTR
+ literal_tag = (Eterm) literals ? TAG_LITERAL_PTR : 0;
+#else
+ literal_tag = (Eterm) 0;
+#endif
for (bp=first; bp!=NULL; bp=bp->next) {
- move_one_frag(hpp, bp, off_heap);
+ move_one_frag(hpp, bp, off_heap, literals);
}
hp_end = *hpp;
for (hp=hp_start; hp<hp_end; ++hp) {
@@ -644,6 +1878,9 @@ void move_multi_frags(Eterm** hpp, ErlOffHeap* off_heap, ErlHeapFragment* first,
val = *ptr;
if (IS_MOVED_BOXED(val)) {
ASSERT(is_boxed(val));
+#ifdef TAG_LITERAL_PTR
+ val |= literal_tag;
+#endif
*hp = val;
}
break;
@@ -651,7 +1888,11 @@ void move_multi_frags(Eterm** hpp, ErlOffHeap* off_heap, ErlHeapFragment* first,
ptr = list_val(gval);
val = *ptr;
if (IS_MOVED_CONS(val)) {
- *hp = ptr[1];
+ val = ptr[1];
+#ifdef TAG_LITERAL_PTR
+ val |= literal_tag;
+#endif
+ *hp = val;
}
break;
case TAG_PRIMARY_HEADER:
@@ -662,12 +1903,12 @@ void move_multi_frags(Eterm** hpp, ErlOffHeap* off_heap, ErlHeapFragment* first,
}
}
for (i=0; i<nrefs; ++i) {
- refs[i] = follow_moved(refs[i]);
+ refs[i] = follow_moved(refs[i], literal_tag);
}
}
static void
-move_one_frag(Eterm** hpp, ErlHeapFragment* frag, ErlOffHeap* off_heap)
+move_one_frag(Eterm** hpp, ErlHeapFragment* frag, ErlOffHeap* off_heap, int literals)
{
Eterm* ptr = frag->mem;
Eterm* end = ptr + frag->used_size;
@@ -704,4 +1945,3 @@ move_one_frag(Eterm** hpp, ErlHeapFragment* frag, ErlOffHeap* off_heap)
OH_OVERHEAD(off_heap, frag->off_heap.overhead);
frag->off_heap.first = NULL;
}
-
diff --git a/erts/emulator/beam/dist.c b/erts/emulator/beam/dist.c
index 10dd6cf206..e31ef29562 100644
--- a/erts/emulator/beam/dist.c
+++ b/erts/emulator/beam/dist.c
@@ -378,10 +378,11 @@ static void doit_node_link_net_exits(ErtsLink *lnk, void *vnecp)
ASSERT(lnk->type == LINK_NODE);
if (is_internal_pid(lnk->pid)) {
ErtsProcLocks rp_locks = ERTS_PROC_LOCK_LINK;
- rp = erts_pid2proc(NULL, 0, lnk->pid, rp_locks);
- if (!rp) {
+ ErlOffHeap *ohp;
+ rp = erts_proc_lookup(lnk->pid);
+ if (!rp)
goto done;
- }
+ erts_smp_proc_lock(rp, rp_locks);
rlnk = erts_remove_link(&ERTS_P_LINKS(rp), name);
if (rlnk != NULL) {
ASSERT(is_atom(rlnk->pid) && (rlnk->type == LINK_NODE));
@@ -389,12 +390,14 @@ static void doit_node_link_net_exits(ErtsLink *lnk, void *vnecp)
}
n = ERTS_LINK_REFC(lnk);
for (i = 0; i < n; ++i) {
- ErlHeapFragment* bp;
- ErlOffHeap *ohp;
Eterm tup;
- Eterm *hp = erts_alloc_message_heap(3,&bp,&ohp,rp,&rp_locks);
+ Eterm *hp;
+ ErtsMessage *msgp;
+
+ msgp = erts_alloc_message_heap(rp, &rp_locks,
+ 3, &hp, &ohp);
tup = TUPLE2(hp, am_nodedown, name);
- erts_queue_message(rp, &rp_locks, bp, tup, NIL);
+ erts_queue_message(rp, &rp_locks, msgp, tup, NIL);
}
erts_smp_proc_unlock(rp, rp_locks);
}
@@ -878,11 +881,7 @@ erts_dsig_send_msg(Eterm remote, Eterm message, ErtsSendContext* ctx)
DTRACE_CHARBUF(receiver_name, 64);
#endif
- if (SEQ_TRACE_TOKEN(sender) != NIL
-#ifdef USE_VM_PROBES
- && SEQ_TRACE_TOKEN(sender) != am_have_dt_utag
-#endif
- ) {
+ if (have_seqtrace(SEQ_TRACE_TOKEN(sender))) {
seq_trace_update_send(sender);
token = SEQ_TRACE_TOKEN(sender);
seq_trace_output(token, message, SEQ_TRACE_SEND, remote, sender);
@@ -897,7 +896,7 @@ erts_dsig_send_msg(Eterm remote, Eterm message, ErtsSendContext* ctx)
erts_snprintf(receiver_name, sizeof(DTRACE_CHARBUF_NAME(receiver_name)),
"%T", remote);
msize = size_object(message);
- if (token != NIL && token != am_have_dt_utag) {
+ if (have_seqtrace(token)) {
tok_label = signed_val(SEQ_TRACE_T_LABEL(token));
tok_lastcnt = signed_val(SEQ_TRACE_T_LASTCNT(token));
tok_serial = signed_val(SEQ_TRACE_T_SERIAL(token));
@@ -939,11 +938,7 @@ erts_dsig_send_reg_msg(Eterm remote_name, Eterm message,
DTRACE_CHARBUF(receiver_name, 128);
#endif
- if (SEQ_TRACE_TOKEN(sender) != NIL
-#ifdef USE_VM_PROBES
- && SEQ_TRACE_TOKEN(sender) != am_have_dt_utag
-#endif
- ) {
+ if (have_seqtrace(SEQ_TRACE_TOKEN(sender))) {
seq_trace_update_send(sender);
token = SEQ_TRACE_TOKEN(sender);
seq_trace_output(token, message, SEQ_TRACE_SEND, remote_name, sender);
@@ -958,7 +953,7 @@ erts_dsig_send_reg_msg(Eterm remote_name, Eterm message,
erts_snprintf(receiver_name, sizeof(DTRACE_CHARBUF_NAME(receiver_name)),
"{%T,%s}", remote_name, node_name);
msize = size_object(message);
- if (token != NIL && token != am_have_dt_utag) {
+ if (have_seqtrace(token)) {
tok_label = signed_val(SEQ_TRACE_T_LABEL(token));
tok_lastcnt = signed_val(SEQ_TRACE_T_LASTCNT(token));
tok_serial = signed_val(SEQ_TRACE_T_SERIAL(token));
@@ -1003,11 +998,7 @@ erts_dsig_send_exit_tt(ErtsDSigData *dsdp, Eterm local, Eterm remote,
#endif
UseTmpHeapNoproc(6);
- if (token != NIL
-#ifdef USE_VM_PROBES
- && token != am_have_dt_utag
-#endif
- ) {
+ if (have_seqtrace(token)) {
seq_trace_update_send(dsdp->proc);
seq_trace_output_exit(token, reason, SEQ_TRACE_SEND, remote, local);
ctl = TUPLE5(&ctl_heap[0],
@@ -1026,7 +1017,7 @@ erts_dsig_send_exit_tt(ErtsDSigData *dsdp, Eterm local, Eterm remote,
"{%T,%s}", remote, node_name);
erts_snprintf(reason_str, sizeof(DTRACE_CHARBUF_NAME(reason_str)),
"%T", reason);
- if (token != NIL && token != am_have_dt_utag) {
+ if (have_seqtrace(token)) {
tok_label = signed_val(SEQ_TRACE_T_LABEL(token));
tok_lastcnt = signed_val(SEQ_TRACE_T_LASTCNT(token));
tok_serial = signed_val(SEQ_TRACE_T_SERIAL(token));
@@ -1145,7 +1136,6 @@ int erts_net_message(Port *prt,
Process* rp;
DeclareTmpHeapNoproc(ctl_default,DIST_CTL_DEFAULT_SIZE);
Eterm* ctl = ctl_default;
- ErlOffHeap off_heap;
ErtsHeapFactory factory;
Eterm* hp;
Sint type;
@@ -1160,9 +1150,6 @@ int erts_net_message(Port *prt,
#endif
UseTmpHeapNoproc(DIST_CTL_DEFAULT_SIZE);
- /* Thanks to Luke Gorrie */
- off_heap.first = NULL;
- off_heap.overhead = 0;
ERTS_SMP_CHK_NO_PROC_LOCKS;
@@ -1223,15 +1210,15 @@ int erts_net_message(Port *prt,
}
hp = ctl;
- erts_factory_static_init(&factory, ctl, ctl_len, &off_heap);
+ erts_factory_tmp_init(&factory, ctl, ctl_len, ERTS_ALC_T_DCTRL_BUF);
arg = erts_decode_dist_ext(&factory, &ede);
if (is_non_value(arg)) {
#ifdef ERTS_DIST_MSG_DBG
- erts_fprintf(stderr, "DIST MSG DEBUG: erts_dist_ext_size(CTL) failed:\n");
+ erts_fprintf(stderr, "DIST MSG DEBUG: erts_decode_dist_ext(CTL) failed:\n");
bw(buf, orig_len);
#endif
PURIFY_MSG("data error");
- goto data_error;
+ goto decode_error;
}
ctl_len = t - buf;
@@ -1462,7 +1449,7 @@ int erts_net_message(Port *prt,
ErlOffHeap *ohp;
ASSERT(xsize);
heap_frag = erts_dist_ext_trailer(ede_copy);
- ERTS_INIT_HEAP_FRAG(heap_frag, token_size);
+ ERTS_INIT_HEAP_FRAG(heap_frag, token_size, token_size);
hp = heap_frag->mem;
ohp = &heap_frag->off_heap;
token = tuple[5];
@@ -1511,7 +1498,7 @@ int erts_net_message(Port *prt,
ErlOffHeap *ohp;
ASSERT(xsize);
heap_frag = erts_dist_ext_trailer(ede_copy);
- ERTS_INIT_HEAP_FRAG(heap_frag, token_size);
+ ERTS_INIT_HEAP_FRAG(heap_frag, token_size, token_size);
hp = heap_frag->mem;
ohp = &heap_frag->off_heap;
token = tuple[4];
@@ -1711,7 +1698,7 @@ int erts_net_message(Port *prt,
goto invalid_message;
}
- erts_cleanup_offheap(&off_heap);
+ erts_factory_close(&factory);
if (ctl != ctl_default) {
erts_free(ERTS_ALC_T_DCTRL_BUF, (void *) ctl);
}
@@ -1724,12 +1711,13 @@ int erts_net_message(Port *prt,
erts_dsprintf(dsbufp, "Invalid distribution message: %.200T", arg);
erts_send_error_to_logger_nogl(dsbufp);
}
- data_error:
+decode_error:
PURIFY_MSG("data error");
- erts_cleanup_offheap(&off_heap);
+ erts_factory_close(&factory);
if (ctl != ctl_default) {
erts_free(ERTS_ALC_T_DCTRL_BUF, (void *) ctl);
}
+data_error:
UnUseTmpHeapNoproc(DIST_CTL_DEFAULT_SIZE);
erts_deliver_port_exit(prt, dep->cid, am_killed, 0);
ERTS_SMP_CHK_NO_PROC_LOCKS;
@@ -2568,7 +2556,9 @@ int distribution_info(int to, void *arg) /* Called by break handler */
}
for (dep = erts_not_connected_dist_entries; dep; dep = dep->next) {
- info_dist_entry(to, arg, dep, 0, 0);
+ if (dep != erts_this_dist_entry) {
+ info_dist_entry(to, arg, dep, 0, 0);
+ }
}
return(0);
@@ -2646,13 +2636,8 @@ BIF_RETTYPE setnode_2(BIF_ALIST_2)
if (!net_kernel)
goto error;
- /* By setting dist_entry==erts_this_dist_entry and DISTRIBUTION on
- net_kernel do_net_exist will be called when net_kernel
- is terminated !! */
- (void) ERTS_PROC_SET_DIST_ENTRY(net_kernel,
- ERTS_PROC_LOCK_MAIN,
- erts_this_dist_entry);
- erts_refc_inc(&erts_this_dist_entry->refc, 2);
+ /* By setting F_DISTRIBUTION on net_kernel,
+ * do_net_exist will be called when net_kernel is terminated !! */
net_kernel->flags |= F_DISTRIBUTION;
if (net_kernel != BIF_P)
@@ -3013,11 +2998,11 @@ BIF_RETTYPE nodes_1(BIF_ALIST_1)
erts_smp_rwmtx_rlock(&erts_dist_table_rwmtx);
- ASSERT(erts_no_of_not_connected_dist_entries >= 0);
+ ASSERT(erts_no_of_not_connected_dist_entries > 0);
ASSERT(erts_no_of_hidden_dist_entries >= 0);
ASSERT(erts_no_of_visible_dist_entries >= 0);
if(not_connected)
- length += erts_no_of_not_connected_dist_entries;
+ length += (erts_no_of_not_connected_dist_entries - 1);
if(hidden)
length += erts_no_of_hidden_dist_entries;
if(visible)
@@ -3039,8 +3024,10 @@ BIF_RETTYPE nodes_1(BIF_ALIST_1)
#endif
if(not_connected)
for(dep = erts_not_connected_dist_entries; dep; dep = dep->next) {
- result = CONS(hp, dep->sysname, result);
- hp += 2;
+ if (dep != erts_this_dist_entry) {
+ result = CONS(hp, dep->sysname, result);
+ hp += 2;
+ }
}
if(hidden)
for(dep = erts_hidden_dist_entries; dep; dep = dep->next) {
@@ -3271,11 +3258,16 @@ send_nodes_mon_msg(Process *rp,
Uint sz)
{
Eterm msg;
- ErlHeapFragment* bp;
+ Eterm *hp;
+ ErtsMessage *mp;
ErlOffHeap *ohp;
- Eterm *hp = erts_alloc_message_heap(sz, &bp, &ohp, rp, rp_locksp);
#ifdef DEBUG
- Eterm *hend = hp + sz;
+ Eterm *hend;
+#endif
+
+ mp = erts_alloc_message_heap(rp, rp_locksp, sz, &hp, &ohp);
+#ifdef DEBUG
+ hend = hp + sz;
#endif
if (!nmp->opts) {
@@ -3321,7 +3313,7 @@ send_nodes_mon_msg(Process *rp,
}
ASSERT(hend == hp);
- erts_queue_message(rp, rp_locksp, bp, msg, NIL);
+ erts_queue_message(rp, rp_locksp, mp, msg, NIL);
}
static void
diff --git a/erts/emulator/beam/erl_alloc.c b/erts/emulator/beam/erl_alloc.c
index d68f22d573..5544712e8d 100644
--- a/erts/emulator/beam/erl_alloc.c
+++ b/erts/emulator/beam/erl_alloc.c
@@ -130,6 +130,8 @@ static ErtsAllocatorState_t binary_alloc_state;
static ErtsAllocatorState_t ets_alloc_state;
static ErtsAllocatorState_t driver_alloc_state;
static ErtsAllocatorState_t fix_alloc_state;
+static ErtsAllocatorState_t literal_alloc_state;
+static ErtsAllocatorState_t test_alloc_state;
typedef struct {
erts_smp_atomic32_t refc;
@@ -211,6 +213,8 @@ typedef struct {
struct au_init ets_alloc;
struct au_init driver_alloc;
struct au_init fix_alloc;
+ struct au_init literal_alloc;
+ struct au_init test_alloc;
} erts_alc_hndl_args_init_t;
#define ERTS_AU_INIT__ {0, 0, 1, GOODFIT, DEFAULT_ALLCTR_INIT, {1,1,1,1}}
@@ -272,9 +276,9 @@ set_default_ll_alloc_opts(struct au_init *ip)
ip->init.util.name_prefix = "ll_";
ip->init.util.alloc_no = ERTS_ALC_A_LONG_LIVED;
#ifndef SMALL_MEMORY
- ip->init.util.mmbcs = 2*1024*1024 - 40; /* Main carrier size */
+ ip->init.util.mmbcs = 2*1024*1024; /* Main carrier size */
#else
- ip->init.util.mmbcs = 1*1024*1024 - 40; /* Main carrier size */
+ ip->init.util.mmbcs = 1*1024*1024; /* Main carrier size */
#endif
ip->init.util.ts = ERTS_ALC_MTA_LONG_LIVED;
ip->init.util.asbcst = 0;
@@ -285,6 +289,51 @@ set_default_ll_alloc_opts(struct au_init *ip)
}
static void
+set_default_literal_alloc_opts(struct au_init *ip)
+{
+ SET_DEFAULT_ALLOC_OPTS(ip);
+ ip->enable = 1;
+ ip->thr_spec = 0;
+ ip->atype = BESTFIT;
+ ip->init.bf.ao = 1;
+ ip->init.util.ramv = 0;
+ ip->init.util.mmsbc = 0;
+ ip->init.util.sbct = ~((UWord) 0);
+ ip->init.util.name_prefix = "literal_";
+ ip->init.util.alloc_no = ERTS_ALC_A_LITERAL;
+#ifndef SMALL_MEMORY
+ ip->init.util.mmbcs = 2*1024*1024; /* Main carrier size */
+#else
+ ip->init.util.mmbcs = 1*1024*1024; /* Main carrier size */
+#endif
+ ip->init.util.ts = ERTS_ALC_MTA_LITERAL;
+ ip->init.util.asbcst = 0;
+ ip->init.util.rsbcst = 0;
+ ip->init.util.rsbcmt = 0;
+ ip->init.util.rmbcmt = 0;
+ ip->init.util.acul = 0;
+
+#if defined(ARCH_32)
+# if HAVE_ERTS_MSEG
+ ip->init.util.mseg_alloc = &erts_alcu_literal_32_mseg_alloc;
+ ip->init.util.mseg_realloc = &erts_alcu_literal_32_mseg_realloc;
+ ip->init.util.mseg_dealloc = &erts_alcu_literal_32_mseg_dealloc;
+# endif
+ ip->init.util.sys_alloc = &erts_alcu_literal_32_sys_alloc;
+ ip->init.util.sys_realloc = &erts_alcu_literal_32_sys_realloc;
+ ip->init.util.sys_dealloc = &erts_alcu_literal_32_sys_dealloc;
+#elif defined(ARCH_64)
+# ifdef ERTS_HAVE_OS_PHYSICAL_MEMORY_RESERVATION
+ ip->init.util.mseg_alloc = &erts_alcu_literal_64_mseg_alloc;
+ ip->init.util.mseg_realloc = &erts_alcu_literal_64_mseg_realloc;
+ ip->init.util.mseg_dealloc = &erts_alcu_literal_64_mseg_dealloc;
+# endif
+#else
+# error Unknown architecture
+#endif
+}
+
+static void
set_default_temp_alloc_opts(struct au_init *ip)
{
SET_DEFAULT_ALLOC_OPTS(ip);
@@ -398,6 +447,33 @@ set_default_fix_alloc_opts(struct au_init *ip,
ip->init.util.acul = ERTS_ALC_DEFAULT_ACUL;
}
+static void
+set_default_test_alloc_opts(struct au_init *ip)
+{
+ SET_DEFAULT_ALLOC_OPTS(ip);
+ ip->enable = 0; /* Disabled by default */
+ ip->thr_spec = -1 * erts_no_schedulers;
+ ip->atype = AOFIRSTFIT;
+ ip->init.aoff.flavor = AOFF_BF;
+ ip->init.util.name_prefix = "test_";
+ ip->init.util.alloc_no = ERTS_ALC_A_TEST;
+ ip->init.util.mmbcs = 0; /* Main carrier size */
+ ip->init.util.ts = ERTS_ALC_MTA_TEST;
+ ip->init.util.acul = ERTS_ALC_DEFAULT_ACUL;
+
+ /* Use a constant minimal MBC size */
+#if ERTS_SA_MB_CARRIERS
+ ip->init.util.smbcs = ERTS_SACRR_UNIT_SZ;
+ ip->init.util.lmbcs = ERTS_SACRR_UNIT_SZ;
+ ip->init.util.sbct = ERTS_SACRR_UNIT_SZ;
+#else
+ ip->init.util.smbcs = 1 << 12;
+ ip->init.util.lmbcs = 1 << 12;
+ ip->init.util.sbct = 1 << 12;
+#endif
+}
+
+
#ifdef ERTS_SMP
static void
@@ -535,7 +611,7 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_DRV_SEL_D_STATE)]
= sizeof(ErtsDrvSelectDataState);
fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_MSG_REF)]
- = sizeof(ErlMessage);
+ = sizeof(ErtsMessageRef);
#ifdef ERTS_SMP
fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_THR_Q_EL_SL)]
= sizeof(ErtsThrQElement_t);
@@ -577,6 +653,8 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
set_default_driver_alloc_opts(&init.driver_alloc);
set_default_fix_alloc_opts(&init.fix_alloc,
fix_type_sizes);
+ set_default_literal_alloc_opts(&init.literal_alloc);
+ set_default_test_alloc_opts(&init.test_alloc);
if (argc && argv)
handle_args(argc, argv, &init);
@@ -604,6 +682,7 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
init.ets_alloc.thr_spec = 0;
init.driver_alloc.thr_spec = 0;
init.fix_alloc.thr_spec = 0;
+ init.literal_alloc.thr_spec = 0;
#endif
/* Make adjustments for carrier migration support */
@@ -616,6 +695,7 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
adjust_carrier_migration_support(&init.ets_alloc);
adjust_carrier_migration_support(&init.driver_alloc);
adjust_carrier_migration_support(&init.fix_alloc);
+ adjust_carrier_migration_support(&init.literal_alloc);
if (init.erts_alloc_config) {
/* Adjust flags that erts_alloc_config won't like */
@@ -630,6 +710,7 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
init.ets_alloc.thr_spec = 0;
init.driver_alloc.thr_spec = 0;
init.fix_alloc.thr_spec = 0;
+ init.literal_alloc.thr_spec = 0;
/* No carrier migration */
init.temp_alloc.init.util.acul = 0;
@@ -641,6 +722,7 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
init.ets_alloc.init.util.acul = 0;
init.driver_alloc.init.util.acul = 0;
init.fix_alloc.init.util.acul = 0;
+ init.literal_alloc.init.util.acul = 0;
}
#ifdef ERTS_SMP
@@ -657,6 +739,7 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
adjust_tpref(&init.ets_alloc, erts_no_schedulers);
adjust_tpref(&init.driver_alloc, erts_no_schedulers);
adjust_tpref(&init.fix_alloc, erts_no_schedulers);
+ adjust_tpref(&init.literal_alloc, erts_no_schedulers);
#else
/* No thread specific if not smp */
@@ -675,6 +758,7 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
refuse_af_strategy(&init.ets_alloc);
refuse_af_strategy(&init.driver_alloc);
refuse_af_strategy(&init.fix_alloc);
+ refuse_af_strategy(&init.literal_alloc);
#ifdef ERTS_SMP
if (!init.temp_alloc.thr_spec)
@@ -685,6 +769,9 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
#if HAVE_ERTS_MSEG
init.mseg.nos = erts_no_schedulers;
erts_mseg_init(&init.mseg);
+# if defined(ARCH_64) && defined(ERTS_HAVE_OS_PHYSICAL_MEMORY_RESERVATION)
+ erts_mmap_init(&erts_literal_mmapper, &init.mseg.literal_mmap);
+# endif
#endif
erts_alcu_init(&init.alloc_util);
@@ -718,6 +805,8 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
set_au_allocator(ERTS_ALC_A_ETS, &init.ets_alloc, ncpu);
set_au_allocator(ERTS_ALC_A_DRIVER, &init.driver_alloc, ncpu);
set_au_allocator(ERTS_ALC_A_FIXED_SIZE, &init.fix_alloc, ncpu);
+ set_au_allocator(ERTS_ALC_A_LITERAL, &init.literal_alloc, ncpu);
+ set_au_allocator(ERTS_ALC_A_TEST, &init.test_alloc, ncpu);
for (i = ERTS_ALC_A_MIN; i <= ERTS_ALC_A_MAX; i++) {
if (!erts_allctrs[i].alloc)
@@ -770,6 +859,13 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
start_au_allocator(ERTS_ALC_A_FIXED_SIZE,
&init.fix_alloc,
&fix_alloc_state);
+ start_au_allocator(ERTS_ALC_A_LITERAL,
+ &init.literal_alloc,
+ &literal_alloc_state);
+
+ start_au_allocator(ERTS_ALC_A_TEST,
+ &init.test_alloc,
+ &test_alloc_state);
erts_mtrace_install_wrapper_functions();
extra_block_size += erts_instr_init(init.instr.stat, init.instr.map);
@@ -952,7 +1048,7 @@ start_au_allocator(ErtsAlcType_t alctr_n,
}
for (i = 0; i < size; i++) {
- void *as;
+ Allctr_t *as;
atype = init->atype;
if (!init->thr_spec)
@@ -989,22 +1085,22 @@ start_au_allocator(ErtsAlcType_t alctr_n,
switch (atype) {
case GOODFIT:
- as = (void *) erts_gfalc_start((GFAllctr_t *) as0,
+ as = erts_gfalc_start((GFAllctr_t *) as0,
&init->init.gf,
&init->init.util);
break;
case BESTFIT:
- as = (void *) erts_bfalc_start((BFAllctr_t *) as0,
+ as = erts_bfalc_start((BFAllctr_t *) as0,
&init->init.bf,
&init->init.util);
break;
case AFIT:
- as = (void *) erts_afalc_start((AFAllctr_t *) as0,
+ as = erts_afalc_start((AFAllctr_t *) as0,
&init->init.af,
&init->init.util);
break;
case AOFIRSTFIT:
- as = (void *) erts_aoffalc_start((AOFFAllctr_t *) as0,
+ as = erts_aoffalc_start((AOFFAllctr_t *) as0,
&init->init.aoff,
&init->init.util);
break;
@@ -1351,6 +1447,7 @@ handle_args(int *argc, char **argv, erts_alc_hndl_args_init_t *init)
&init->fix_alloc,
&init->sl_alloc,
&init->temp_alloc
+ /* test_alloc not affected by +Mea??? or +Mu??? */
};
int aui_sz = (int) sizeof(aui)/sizeof(aui[0]);
char *arg;
@@ -1406,25 +1503,25 @@ handle_args(int *argc, char **argv, erts_alc_hndl_args_init_t *init)
}
else if (has_prefix("scs", argv[i]+3)) {
#if HAVE_ERTS_MSEG
- init->mseg.mmap.scs =
+ init->mseg.dflt_mmap.scs =
#endif
get_mb_value(argv[i]+6, argv, &i);
}
else if (has_prefix("sco", argv[i]+3)) {
#if HAVE_ERTS_MSEG
- init->mseg.mmap.sco =
+ init->mseg.dflt_mmap.sco =
#endif
get_bool_value(argv[i]+6, argv, &i);
}
else if (has_prefix("scrpm", argv[i]+3)) {
#if HAVE_ERTS_MSEG
- init->mseg.mmap.scrpm =
+ init->mseg.dflt_mmap.scrpm =
#endif
get_bool_value(argv[i]+8, argv, &i);
}
else if (has_prefix("scrfsd", argv[i]+3)) {
#if HAVE_ERTS_MSEG
- init->mseg.mmap.scrfsd =
+ init->mseg.dflt_mmap.scrfsd =
#endif
get_amount_value(argv[i]+9, argv, &i);
}
@@ -1441,6 +1538,9 @@ handle_args(int *argc, char **argv, erts_alc_hndl_args_init_t *init)
case 'T':
handle_au_arg(&init->temp_alloc, &argv[i][3], argv, &i, 0);
break;
+ case 'Z':
+ handle_au_arg(&init->test_alloc, &argv[i][3], argv, &i, 0);
+ break;
case 'Y': { /* sys_alloc */
if (has_prefix("tt", param+2)) {
/* set trim threshold */
@@ -2093,11 +2193,12 @@ erts_memory(int *print_to_p, void *print_to_arg, void *proc, Eterm earg)
return am_badarg;
}
- /* All alloc_util allocators *have* to be enabled */
+ /* All alloc_util allocators *have* to be enabled, except test_alloc */
for (ai = ERTS_ALC_A_MIN; ai <= ERTS_ALC_A_MAX; ai++) {
switch (ai) {
case ERTS_ALC_A_SYSTEM:
+ case ERTS_ALC_A_TEST:
break;
default:
if (!erts_allctrs_info[ai].enabled
@@ -2138,6 +2239,8 @@ erts_memory(int *print_to_p, void *print_to_arg, void *proc, Eterm earg)
* contain any allocated memory.
*/
continue;
+ case ERTS_ALC_A_TEST:
+ continue;
case ERTS_ALC_A_EHEAP:
save = &size.processes;
break;
@@ -2539,14 +2642,17 @@ erts_alloc_util_allocators(void *proc)
/*
* Currently all allocators except sys_alloc are
* alloc_util allocators.
+ * Also hide test_alloc which is disabled by default
+ * and only intended for our own testing.
*/
- sz = ((ERTS_ALC_A_MAX + 1 - ERTS_ALC_A_MIN) - 1)*2;
+ sz = ((ERTS_ALC_A_MAX + 1 - ERTS_ALC_A_MIN) - 2)*2;
ASSERT(sz > 0);
hp = HAlloc((Process *) proc, sz);
res = NIL;
for (i = ERTS_ALC_A_MAX; i >= ERTS_ALC_A_MIN; i--) {
switch (i) {
case ERTS_ALC_A_SYSTEM:
+ case ERTS_ALC_A_TEST:
break;
default: {
char *alc_str = (char *) ERTS_ALC_A2AD(i);
@@ -2629,7 +2735,7 @@ erts_allocator_info(int to, void *arg)
erts_mseg_info(i, &to, arg, 0, NULL, NULL);
}
erts_print(to, arg, "=allocator:mseg_alloc.erts_mmap\n");
- erts_mmap_info(&to, arg, NULL, NULL, &emis);
+ erts_mmap_info(&erts_dflt_mmapper, &to, arg, NULL, NULL, &emis);
}
#endif
@@ -2855,12 +2961,12 @@ reply_alloc_info(void *vair)
int global_instances = air->req_sched == sched_id;
ErtsProcLocks rp_locks;
Process *rp = air->proc;
- Eterm ref_copy = NIL, ai_list, msg;
- Eterm *hp = NULL, *hp_end = NULL, *hp_start = NULL;
+ Eterm ref_copy = NIL, ai_list, msg = NIL;
+ Eterm *hp = NULL, *hp_start = NULL, *hp_end = NULL;
Eterm **hpp;
Uint sz, *szp;
ErlOffHeap *ohp = NULL;
- ErlHeapFragment *bp = NULL;
+ ErtsMessage *mp = NULL;
struct erts_mmap_info_struct emis;
int i;
Eterm (*info_func)(Allctr_t *,
@@ -2981,7 +3087,8 @@ reply_alloc_info(void *vair)
ai_list = erts_bld_cons(hpp, szp,
ainfo, ai_list);
- ainfo = (air->only_sz ? NIL : erts_mmap_info(NULL, NULL, hpp, szp, &emis));
+ ainfo = (air->only_sz ? NIL :
+ erts_mmap_info(&erts_dflt_mmapper, NULL, NULL, hpp, szp, &emis));
ainfo = erts_bld_tuple3(hpp, szp,
alloc_atom,
erts_bld_atom(hpp,szp,"erts_mmap"),
@@ -3061,20 +3168,17 @@ reply_alloc_info(void *vair)
if (hpp)
break;
- hp = erts_alloc_message_heap(sz, &bp, &ohp, rp, &rp_locks);
+ mp = erts_alloc_message_heap(rp, &rp_locks, sz, &hp, &ohp);
hp_start = hp;
hp_end = hp + sz;
szp = NULL;
hpp = &hp;
}
- if (bp)
- bp = erts_resize_message_buffer(bp, hp - hp_start, &msg, 1);
- else {
- ASSERT(hp);
- HRelease(rp, hp_end, hp);
- }
- erts_queue_message(rp, &rp_locks, bp, msg, NIL);
+ if (hp != hp_end)
+ erts_shrink_message_heap(&mp, rp, hp_start, hp, hp_end, &msg, 1);
+
+ erts_queue_message(rp, &rp_locks, mp, msg, NIL);
if (air->req_sched == sched_id)
rp_locks &= ~ERTS_PROC_LOCK_MAIN;
@@ -3430,6 +3534,41 @@ UWord erts_alc_test(UWord op, UWord a1, UWord a2, UWord a3)
#else
case 0xf13: return (UWord) 0;
#endif
+ case 0xf14: return (UWord) erts_alloc(ERTS_ALC_T_TEST, (Uint)a1);
+
+ case 0xf15: erts_free(ERTS_ALC_T_TEST, (void*)a1); return 0;
+
+ case 0xf16: {
+ Uint extra_hdr_sz = UNIT_CEILING((Uint)a1);
+ ErtsAllocatorThrSpec_t* ts = &erts_allctr_thr_spec[ERTS_ALC_A_TEST];
+ Uint offset = ts->allctr[0]->mbc_header_size;
+ void* orig_creating_mbc = ts->allctr[0]->creating_mbc;
+ void* orig_destroying_mbc = ts->allctr[0]->destroying_mbc;
+ void* new_creating_mbc = *(void**)a2; /* inout arg */
+ void* new_destroying_mbc = *(void**)a3; /* inout arg */
+ int i;
+
+ for (i=0; i < ts->size; i++) {
+ Allctr_t* ap = ts->allctr[i];
+ if (ap->mbc_header_size != offset
+ || ap->creating_mbc != orig_creating_mbc
+ || ap->destroying_mbc != orig_destroying_mbc
+ || ap->mbc_list.first != NULL)
+ return -1;
+ }
+ for (i=0; i < ts->size; i++) {
+ ts->allctr[i]->mbc_header_size += extra_hdr_sz;
+ ts->allctr[i]->creating_mbc = new_creating_mbc;
+ ts->allctr[i]->destroying_mbc = new_destroying_mbc;
+ }
+ *(void**)a2 = orig_creating_mbc;
+ *(void**)a3 = orig_destroying_mbc;
+ return offset;
+ }
+ case 0xf17: {
+ ErtsAllocatorThrSpec_t* ts = &erts_allctr_thr_spec[ERTS_ALC_A_TEST];
+ return ts->allctr[0]->largest_mbc_size;
+ }
default:
break;
}
diff --git a/erts/emulator/beam/erl_alloc.h b/erts/emulator/beam/erl_alloc.h
index f540bae20d..14e80960f5 100644
--- a/erts/emulator/beam/erl_alloc.h
+++ b/erts/emulator/beam/erl_alloc.h
@@ -30,6 +30,7 @@
#ifdef USE_THREADS
#include "erl_threads.h"
#endif
+#include "erl_mmap.h"
#ifdef DEBUG
# undef ERTS_ALC_WANT_INLINE
@@ -43,9 +44,11 @@
#if ERTS_CAN_INLINE && ERTS_ALC_WANT_INLINE
# define ERTS_ALC_DO_INLINE 1
# define ERTS_ALC_INLINE static ERTS_INLINE
+# define ERTS_ALC_FORCE_INLINE static ERTS_FORCE_INLINE
#else
# define ERTS_ALC_DO_INLINE 0
# define ERTS_ALC_INLINE
+# define ERTS_ALC_FORCE_INLINE
#endif
#define ERTS_ALC_NO_FIXED_SIZES \
@@ -177,6 +180,12 @@ void sys_free(void *) __deprecated; /* erts_free() */
void *sys_alloc(Uint ) __deprecated; /* erts_alloc_fnf() */
void *sys_realloc(void *, Uint) __deprecated; /* erts_realloc_fnf() */
+#undef ERTS_HAVE_IS_IN_LITERAL_RANGE
+#if defined(ARCH_32) || defined(ERTS_HAVE_OS_PHYSICAL_MEMORY_RESERVATION)
+# define ERTS_HAVE_IS_IN_LITERAL_RANGE
+#endif
+
+
/*
* erts_alloc[_fnf](), erts_realloc[_fnf](), erts_free() works as
* malloc(), realloc(), and free() with the following exceptions:
@@ -204,6 +213,9 @@ void erts_free(ErtsAlcType_t type, void *ptr);
void *erts_alloc_fnf(ErtsAlcType_t type, Uint size);
void *erts_realloc_fnf(ErtsAlcType_t type, void *ptr, Uint size);
int erts_is_allctr_wrapper_prelocked(void);
+#ifdef ERTS_HAVE_IS_IN_LITERAL_RANGE
+int erts_is_in_literal_range(void* ptr);
+#endif
#endif /* #if !ERTS_ALC_DO_INLINE */
@@ -281,6 +293,28 @@ int erts_is_allctr_wrapper_prelocked(void)
&& !!erts_tsd_get(erts_allctr_prelock_tsd_key); /* by me */
}
+#ifdef ERTS_HAVE_IS_IN_LITERAL_RANGE
+
+ERTS_ALC_FORCE_INLINE
+int erts_is_in_literal_range(void* ptr)
+{
+#if defined(ARCH_32)
+ Uint ix = (UWord)ptr >> ERTS_MMAP_SUPERALIGNED_BITS;
+
+ return erts_literal_vspace_map[ix / ERTS_VSPACE_WORD_BITS]
+ & ((UWord)1 << (ix % ERTS_VSPACE_WORD_BITS));
+
+#elif defined(ARCH_64)
+ extern char* erts_literals_start;
+ extern UWord erts_literals_size;
+ return ErtsInArea(ptr, erts_literals_start, erts_literals_size);
+#else
+# error No ARCH_xx
+#endif
+}
+
+#endif /* ERTS_HAVE_IS_IN_LITERAL_RANGE */
+
#endif /* #if ERTS_ALC_DO_INLINE || defined(ERTS_ALC_INTERNAL__) */
#define ERTS_ALC_GET_THR_IX() ((int) erts_get_scheduler_id())
diff --git a/erts/emulator/beam/erl_alloc.types b/erts/emulator/beam/erl_alloc.types
index 4804fb407d..e0bc71c88a 100644
--- a/erts/emulator/beam/erl_alloc.types
+++ b/erts/emulator/beam/erl_alloc.types
@@ -86,6 +86,7 @@ allocator LONG_LIVED true ll_alloc
allocator EHEAP true eheap_alloc
allocator ETS true ets_alloc
allocator FIXED_SIZE true fix_alloc
+allocator LITERAL true literal_alloc
+else # Non smp build
@@ -96,13 +97,14 @@ allocator LONG_LIVED false ll_alloc
allocator EHEAP false eheap_alloc
allocator ETS false ets_alloc
allocator FIXED_SIZE false fix_alloc
+allocator LITERAL false literal_alloc
+endif
allocator BINARY true binary_alloc
allocator DRIVER true driver_alloc
-
+allocator TEST true test_alloc
# --- Class declarations -----------------------------------------------------
#
@@ -150,6 +152,8 @@ type OLD_HEAP EHEAP PROCESSES old_heap
type HEAP_FRAG EHEAP PROCESSES heap_frag
type TMP_HEAP TEMPORARY PROCESSES tmp_heap
type MSG_REF FIXED_SIZE PROCESSES msg_ref
+type MSG EHEAP PROCESSES message
+type MSGQ_CHNG SHORT_LIVED PROCESSES messages_queue_change
type MSG_ROOTS TEMPORARY PROCESSES msg_roots
type ROOTSET TEMPORARY PROCESSES root_set
type LOADER_TMP TEMPORARY CODE loader_tmp
@@ -343,6 +347,7 @@ type DDLL_PROCESS STANDARD SYSTEM ddll_processes
type MONITOR_LH STANDARD PROCESSES monitor_lh
type NLINK_LH STANDARD PROCESSES nlink_lh
type CODE LONG_LIVED CODE code
+type LITERAL LITERAL CODE literal
type DB_HEIR_DATA STANDARD ETS db_heir_data
type DB_MS_PSDO_PROC LONG_LIVED ETS db_match_pseudo_proc
type SCHDLR_DATA LONG_LIVED SYSTEM scheduler_data
@@ -405,4 +410,7 @@ type CON_VPRINTF_BUF TEMPORARY SYSTEM con_vprintf_buf
+endif
+# This type should only be used for test
+type TEST TEST SYSTEM testing
+
# ----------------------------------------------------------------------------
diff --git a/erts/emulator/beam/erl_alloc_util.c b/erts/emulator/beam/erl_alloc_util.c
index db4c30b9eb..eedfd1e13d 100644
--- a/erts/emulator/beam/erl_alloc_util.c
+++ b/erts/emulator/beam/erl_alloc_util.c
@@ -751,12 +751,77 @@ internal_free(void *ptr)
#endif
+#ifdef ARCH_32
+
+/*
+ * Bit vector for the entire 32-bit virtual address space
+ * with one bit for each super aligned memory segment.
+ */
+
+#define VSPACE_MAP_BITS (1 << (32 - ERTS_MMAP_SUPERALIGNED_BITS))
+#define VSPACE_MAP_SZ (VSPACE_MAP_BITS / ERTS_VSPACE_WORD_BITS)
+
+static ERTS_INLINE void set_bit(UWord* map, Uint ix)
+{
+ ASSERT(ix / ERTS_VSPACE_WORD_BITS < VSPACE_MAP_SZ);
+ map[ix / ERTS_VSPACE_WORD_BITS]
+ |= ((UWord)1 << (ix % ERTS_VSPACE_WORD_BITS));
+}
+
+static ERTS_INLINE void clr_bit(UWord* map, Uint ix)
+{
+ ASSERT(ix / ERTS_VSPACE_WORD_BITS < VSPACE_MAP_SZ);
+ map[ix / ERTS_VSPACE_WORD_BITS]
+ &= ~((UWord)1 << (ix % ERTS_VSPACE_WORD_BITS));
+}
+
+static ERTS_INLINE int is_bit_set(UWord* map, Uint ix)
+{
+ ASSERT(ix / ERTS_VSPACE_WORD_BITS < VSPACE_MAP_SZ);
+ return map[ix / ERTS_VSPACE_WORD_BITS]
+ & ((UWord)1 << (ix % ERTS_VSPACE_WORD_BITS));
+}
+
+UWord erts_literal_vspace_map[VSPACE_MAP_SZ];
+
+static void set_literal_range(void* start, Uint size)
+{
+ Uint ix = (UWord)start >> ERTS_MMAP_SUPERALIGNED_BITS;
+ Uint n = size >> ERTS_MMAP_SUPERALIGNED_BITS;
+
+ ASSERT(!((UWord)start & ERTS_INV_SUPERALIGNED_MASK));
+ ASSERT(!((UWord)size & ERTS_INV_SUPERALIGNED_MASK));
+ ASSERT(n);
+ while (n--) {
+ ASSERT(!is_bit_set(erts_literal_vspace_map, ix));
+ set_bit(erts_literal_vspace_map, ix);
+ ix++;
+ }
+}
+
+static void clear_literal_range(void* start, Uint size)
+{
+ Uint ix = (UWord)start >> ERTS_MMAP_SUPERALIGNED_BITS;
+ Uint n = size >> ERTS_MMAP_SUPERALIGNED_BITS;
+
+ ASSERT(!((UWord)start & ERTS_INV_SUPERALIGNED_MASK));
+ ASSERT(!((UWord)size & ERTS_INV_SUPERALIGNED_MASK));
+ ASSERT(n);
+ while (n--) {
+ ASSERT(is_bit_set(erts_literal_vspace_map, ix));
+ clr_bit(erts_literal_vspace_map, ix);
+ ix++;
+ }
+}
+
+#endif /* ARCH_32 */
+
/* mseg ... */
#if HAVE_ERTS_MSEG
-static ERTS_INLINE void *
-alcu_mseg_alloc(Allctr_t *allctr, Uint *size_p, Uint flags)
+void*
+erts_alcu_mseg_alloc(Allctr_t *allctr, Uint *size_p, Uint flags)
{
void *res;
UWord size = (UWord) *size_p;
@@ -766,8 +831,9 @@ alcu_mseg_alloc(Allctr_t *allctr, Uint *size_p, Uint flags)
return res;
}
-static ERTS_INLINE void *
-alcu_mseg_realloc(Allctr_t *allctr, void *seg, Uint old_size, Uint *new_size_p)
+void*
+erts_alcu_mseg_realloc(Allctr_t *allctr, void *seg,
+ Uint old_size, Uint *new_size_p)
{
void *res;
UWord new_size = (UWord) *new_size_p;
@@ -778,17 +844,103 @@ alcu_mseg_realloc(Allctr_t *allctr, void *seg, Uint old_size, Uint *new_size_p)
return res;
}
-static ERTS_INLINE void
-alcu_mseg_dealloc(Allctr_t *allctr, void *seg, Uint size, Uint flags)
+void
+erts_alcu_mseg_dealloc(Allctr_t *allctr, void *seg, Uint size, Uint flags)
{
erts_mseg_dealloc_opt(allctr->alloc_no, seg, (UWord) size, flags, &allctr->mseg_opt);
INC_CC(allctr->calls.mseg_dealloc);
}
-#endif
-static ERTS_INLINE void *
-alcu_sys_alloc(Allctr_t *allctr, Uint size, int superalign)
+#if defined(ARCH_32)
+
+void*
+erts_alcu_literal_32_mseg_alloc(Allctr_t *allctr, Uint *size_p, Uint flags)
+{
+ void* res;
+ ERTS_LC_ASSERT(allctr->alloc_no == ERTS_ALC_A_LITERAL
+ && !allctr->t && allctr->thread_safe);
+
+ res = erts_alcu_mseg_alloc(allctr, size_p, flags);
+ if (res)
+ set_literal_range(res, *size_p);
+ return res;
+}
+
+void*
+erts_alcu_literal_32_mseg_realloc(Allctr_t *allctr, void *seg,
+ Uint old_size, Uint *new_size_p)
+{
+ void* res;
+ ERTS_LC_ASSERT(allctr->alloc_no == ERTS_ALC_A_LITERAL
+ && !allctr->t && allctr->thread_safe);
+
+ if (seg && old_size)
+ clear_literal_range(seg, old_size);
+ res = erts_alcu_mseg_realloc(allctr, seg, old_size, new_size_p);
+ if (res)
+ set_literal_range(res, *new_size_p);
+ return res;
+}
+
+void
+erts_alcu_literal_32_mseg_dealloc(Allctr_t *allctr, void *seg, Uint size,
+ Uint flags)
+{
+ ERTS_LC_ASSERT(allctr->alloc_no == ERTS_ALC_A_LITERAL
+ && !allctr->t && allctr->thread_safe);
+
+ erts_alcu_mseg_dealloc(allctr, seg, size, flags);
+
+ clear_literal_range(seg, size);
+}
+
+#elif defined(ARCH_64) && defined(ERTS_HAVE_OS_PHYSICAL_MEMORY_RESERVATION)
+
+void*
+erts_alcu_literal_64_mseg_alloc(Allctr_t *allctr, Uint *size_p, Uint flags)
+{
+ void* res;
+ UWord size = (UWord) *size_p;
+ Uint32 mmap_flags = ERTS_MMAPFLG_SUPERCARRIER_ONLY;
+ if (flags & ERTS_MSEG_FLG_2POW)
+ mmap_flags |= ERTS_MMAPFLG_SUPERALIGNED;
+
+ res = erts_mmap(&erts_literal_mmapper, mmap_flags, &size);
+ *size_p = (Uint)size;
+ INC_CC(allctr->calls.mseg_alloc);
+ return res;
+}
+
+void*
+erts_alcu_literal_64_mseg_realloc(Allctr_t *allctr, void *seg,
+ Uint old_size, Uint *new_size_p)
+{
+ void *res;
+ UWord new_size = (UWord) *new_size_p;
+ res = erts_mremap(&erts_literal_mmapper, ERTS_MSEG_FLG_NONE, seg, old_size, &new_size);
+ *new_size_p = (Uint) new_size;
+ INC_CC(allctr->calls.mseg_realloc);
+ return res;
+}
+
+void
+erts_alcu_literal_64_mseg_dealloc(Allctr_t *allctr, void *seg, Uint size,
+ Uint flags)
+{
+ Uint32 mmap_flags = ERTS_MMAPFLG_SUPERCARRIER_ONLY;
+ if (flags & ERTS_MSEG_FLG_2POW)
+ mmap_flags |= ERTS_MMAPFLG_SUPERALIGNED;
+
+ erts_munmap(&erts_literal_mmapper, mmap_flags, seg, (UWord)size);
+ INC_CC(allctr->calls.mseg_dealloc);
+}
+#endif /* ARCH_64 && ERTS_HAVE_OS_PHYSICAL_MEMORY_RESERVATION */
+
+#endif /* HAVE_ERTS_MSEG */
+
+void*
+erts_alcu_sys_alloc(Allctr_t *allctr, Uint size, int superalign)
{
void *res;
#if ERTS_SA_MB_CARRIERS && ERTS_HAVE_ERTS_SYS_ALIGNED_ALLOC
@@ -803,8 +955,8 @@ alcu_sys_alloc(Allctr_t *allctr, Uint size, int superalign)
return res;
}
-static ERTS_INLINE void *
-alcu_sys_realloc(Allctr_t *allctr, void *ptr, Uint size, Uint old_size, int superalign)
+void*
+erts_alcu_sys_realloc(Allctr_t *allctr, void *ptr, Uint size, Uint old_size, int superalign)
{
void *res;
@@ -824,8 +976,8 @@ alcu_sys_realloc(Allctr_t *allctr, void *ptr, Uint size, Uint old_size, int supe
return res;
}
-static ERTS_INLINE void
-alcu_sys_free(Allctr_t *allctr, void *ptr, int superalign)
+void
+erts_alcu_sys_dealloc(Allctr_t *allctr, void *ptr, Uint size, int superalign)
{
#if ERTS_SA_MB_CARRIERS && ERTS_HAVE_ERTS_SYS_ALIGNED_ALLOC
if (superalign)
@@ -838,6 +990,49 @@ alcu_sys_free(Allctr_t *allctr, void *ptr, int superalign)
erts_mtrace_crr_free(allctr->alloc_no, ERTS_ALC_A_SYSTEM, ptr);
}
+#ifdef ARCH_32
+
+void*
+erts_alcu_literal_32_sys_alloc(Allctr_t *allctr, Uint size, int superalign)
+{
+ void* res;
+ ERTS_LC_ASSERT(allctr->alloc_no == ERTS_ALC_A_LITERAL
+ && !allctr->t && allctr->thread_safe);
+
+ res = erts_alcu_sys_alloc(allctr, size, 1);
+ if (res)
+ set_literal_range(res, size);
+ return res;
+}
+
+void*
+erts_alcu_literal_32_sys_realloc(Allctr_t *allctr, void *ptr, Uint size, Uint old_size, int superalign)
+{
+ void* res;
+ ERTS_LC_ASSERT(allctr->alloc_no == ERTS_ALC_A_LITERAL
+ && !allctr->t && allctr->thread_safe);
+
+ if (ptr && old_size)
+ clear_literal_range(ptr, old_size);
+ res = erts_alcu_sys_realloc(allctr, ptr, size, old_size, 1);
+ if (res)
+ set_literal_range(res, size);
+ return res;
+}
+
+void
+erts_alcu_literal_32_sys_dealloc(Allctr_t *allctr, void *ptr, Uint size, int superalign)
+{
+ ERTS_LC_ASSERT(allctr->alloc_no == ERTS_ALC_A_LITERAL
+ && !allctr->t && allctr->thread_safe);
+
+ erts_alcu_sys_dealloc(allctr, ptr, size, 1);
+
+ clear_literal_range(ptr, size);
+}
+
+#endif /* ARCH_32 */
+
static Uint
get_next_mbc_size(Allctr_t *allctr)
{
@@ -1437,6 +1632,16 @@ erts_alcu_fix_alloc_shrink(Allctr_t *allctr, erts_aint32_t flgs)
static void dealloc_carrier(Allctr_t *allctr, Carrier_t *crr, int superaligned);
+static ERTS_INLINE void
+dealloc_mbc(Allctr_t *allctr, Carrier_t *crr)
+{
+ ASSERT(IS_MB_CARRIER(crr));
+ if (allctr->destroying_mbc)
+ allctr->destroying_mbc(allctr, crr);
+
+ dealloc_carrier(allctr, crr, 1);
+}
+
#ifdef ERTS_SMP
static ERTS_INLINE Allctr_t*
@@ -3149,7 +3354,7 @@ cpool_fetch(Allctr_t *allctr, UWord size)
cpool_entrance = sentinel;
cpdp = cpool_aint2cpd(cpool_read(&cpool_entrance->prev));
if (cpdp == sentinel)
- return NULL;
+ goto check_dc_list;
}
has_passed_sentinel = 0;
@@ -3160,18 +3365,18 @@ cpool_fetch(Allctr_t *allctr, UWord size)
if (cpool_entrance == sentinel) {
cpdp = cpool_aint2cpd(cpool_read(&cpdp->prev));
if (cpdp == sentinel)
- return NULL;
+ break;
}
i = 0; /* Last one to inspect */
}
else if (cpdp == sentinel) {
if (has_passed_sentinel) {
/* We been here before. cpool_entrance must have been removed */
- return NULL;
+ break;
}
cpdp = cpool_aint2cpd(cpool_read(&cpdp->prev));
if (cpdp == sentinel)
- return NULL;
+ break;
has_passed_sentinel = 1;
}
crr = (Carrier_t *)(((char *)cpdp) - offsetof(Carrier_t, cpool));
@@ -3195,10 +3400,12 @@ cpool_fetch(Allctr_t *allctr, UWord size)
return NULL;
}
+check_dc_list:
/* Last; check our own pending dealloc carrier list... */
crr = allctr->cpool.dc_list.last;
while (crr) {
if (erts_atomic_read_nob(&crr->cpool.max_size) >= size) {
+ Block_t* blk;
unlink_carrier(&allctr->cpool.dc_list, crr);
#ifdef ERTS_ALC_CPOOL_DEBUG
ERTS_ALC_CPOOL_ASSERT(erts_smp_atomic_xchg_nob(&crr->allctr,
@@ -3207,6 +3414,9 @@ cpool_fetch(Allctr_t *allctr, UWord size)
#else
erts_smp_atomic_set_nob(&crr->allctr, ((erts_aint_t) allctr));
#endif
+ blk = MBC_TO_FIRST_BLK(allctr, crr);
+ ASSERT(FBLK_TO_MBC(blk) == crr);
+ allctr->link_free_block(allctr, blk);
return crr;
}
crr = crr->prev;
@@ -3237,7 +3447,7 @@ check_pending_dealloc_carrier(Allctr_t *allctr,
dcrr = crr;
crr = crr->next;
- dealloc_carrier(allctr, dcrr, 1);
+ dealloc_mbc(allctr, dcrr);
i++;
} while (crr && i < ERTS_ALC_MAX_DEALLOC_CARRIER);
@@ -3268,18 +3478,20 @@ static void
schedule_dealloc_carrier(Allctr_t *allctr, Carrier_t *crr)
{
Allctr_t *orig_allctr;
+ Block_t *blk;
int check_pending_dealloc;
erts_aint_t max_size;
+ ASSERT(IS_MB_CARRIER(crr));
+
if (!ERTS_ALC_IS_CPOOL_ENABLED(allctr)) {
- dealloc_carrier(allctr, crr, 1);
+ dealloc_mbc(allctr, crr);
return;
}
orig_allctr = crr->cpool.orig_allctr;
if (allctr != orig_allctr) {
- Block_t *blk = MBC_TO_FIRST_BLK(allctr, crr);
int cinit = orig_allctr->dd.ix - allctr->dd.ix;
/*
@@ -3296,6 +3508,7 @@ schedule_dealloc_carrier(Allctr_t *allctr, Carrier_t *crr)
* since the block is an mbc block that is free and last
* in the carrier.
*/
+ blk = MBC_TO_FIRST_BLK(allctr, crr);
ERTS_ALC_CPOOL_ASSERT(IS_FREE_LAST_MBC_BLK(blk));
ERTS_ALC_CPOOL_ASSERT(IS_MBC_FIRST_ABLK(allctr, blk));
@@ -3315,11 +3528,13 @@ schedule_dealloc_carrier(Allctr_t *allctr, Carrier_t *crr)
if (crr->cpool.thr_prgr == ERTS_THR_PRGR_INVALID
|| erts_thr_progress_has_reached(crr->cpool.thr_prgr)) {
- dealloc_carrier(allctr, crr, 1);
+ dealloc_mbc(allctr, crr);
return;
}
- max_size = (erts_aint_t) allctr->largest_fblk_in_mbc(allctr, crr);
+ blk = MBC_TO_FIRST_BLK(allctr, crr);
+ ASSERT(IS_FREE_LAST_MBC_BLK(blk));
+ max_size = (erts_aint_t) MBC_FBLK_SZ(blk);
erts_atomic_set_nob(&crr->cpool.max_size, max_size);
crr->next = NULL;
@@ -3519,6 +3734,8 @@ create_carrier(Allctr_t *allctr, Uint umem_sz, UWord flags)
return NULL;
#endif
}
+ flags |= allctr->crr_set_flgs;
+ flags &= ~allctr->crr_clr_flgs;
ASSERT((flags & CFLG_SBC && !(flags & CFLG_MBC))
|| (flags & CFLG_MBC && !(flags & CFLG_SBC)));
@@ -3534,7 +3751,21 @@ create_carrier(Allctr_t *allctr, Uint umem_sz, UWord flags)
return NULL;
}
- blk_sz = UMEMSZ2BLKSZ(allctr, umem_sz);
+ if (flags & CFLG_MAIN_CARRIER) {
+ ASSERT(flags & CFLG_MBC);
+ ASSERT(flags & CFLG_NO_CPOOL);
+ ASSERT(umem_sz == allctr->main_carrier_size);
+ ERTS_UNDEF(blk_sz, 0);
+
+ if (allctr->main_carrier_size < allctr->min_mbc_size)
+ allctr->main_carrier_size = allctr->min_mbc_size;
+ crr_sz = bcrr_sz = allctr->main_carrier_size;
+ }
+ else {
+ ERTS_UNDEF(bcrr_sz, 0);
+ ERTS_UNDEF(crr_sz, 0);
+ blk_sz = UMEMSZ2BLKSZ(allctr, umem_sz);
+ }
#ifdef ERTS_SMP
allctr->cpool.disable_abandon = ERTS_ALC_CPOOL_MAX_DISABLE_ABANDON;
@@ -3580,13 +3811,15 @@ create_carrier(Allctr_t *allctr, Uint umem_sz, UWord flags)
mseg_flags = ERTS_MSEG_FLG_NONE;
}
else {
- crr_sz = (*allctr->get_next_mbc_size)(allctr);
- if (crr_sz < MBC_HEADER_SIZE(allctr) + blk_sz)
- crr_sz = MBC_HEADER_SIZE(allctr) + blk_sz;
- mseg_flags = ERTS_MSEG_FLG_2POW;
+ if (!(flags & CFLG_MAIN_CARRIER)) {
+ crr_sz = (*allctr->get_next_mbc_size)(allctr);
+ if (crr_sz < MBC_HEADER_SIZE(allctr) + blk_sz)
+ crr_sz = MBC_HEADER_SIZE(allctr) + blk_sz;
+ }
+ mseg_flags = ERTS_MSEG_FLG_2POW;
}
- crr = (Carrier_t *) alcu_mseg_alloc(allctr, &crr_sz, mseg_flags);
+ crr = (Carrier_t *) allctr->mseg_alloc(allctr, &crr_sz, mseg_flags);
if (!crr) {
have_tried_mseg = 1;
if (!(have_tried_sys_alloc || flags & CFLG_FORCE_MSEG))
@@ -3618,23 +3851,22 @@ create_carrier(Allctr_t *allctr, Uint umem_sz, UWord flags)
if (flags & CFLG_SBC) {
bcrr_sz = blk_sz + SBC_HEADER_SIZE;
}
- else {
+ else if (!(flags & CFLG_MAIN_CARRIER)) {
bcrr_sz = MBC_HEADER_SIZE(allctr) + blk_sz;
- if (!(flags & CFLG_MAIN_CARRIER)
- && bcrr_sz < allctr->smallest_mbc_size)
- bcrr_sz = allctr->smallest_mbc_size;
+ if (bcrr_sz < allctr->smallest_mbc_size)
+ bcrr_sz = allctr->smallest_mbc_size;
}
crr_sz = (flags & CFLG_FORCE_SIZE
? UNIT_CEILING(bcrr_sz)
: SYS_ALLOC_CARRIER_CEILING(bcrr_sz));
- crr = (Carrier_t *) alcu_sys_alloc(allctr, crr_sz, flags & CFLG_MBC);
+ crr = (Carrier_t *) allctr->sys_alloc(allctr, crr_sz, flags & CFLG_MBC);
if (!crr) {
if (crr_sz > UNIT_CEILING(bcrr_sz)) {
crr_sz = UNIT_CEILING(bcrr_sz);
- crr = (Carrier_t *) alcu_sys_alloc(allctr, crr_sz, flags & CFLG_MBC);
+ crr = (Carrier_t *) allctr->sys_alloc(allctr, crr_sz, flags & CFLG_MBC);
}
if (!crr) {
#if HAVE_ERTS_MSEG
@@ -3733,7 +3965,7 @@ resize_carrier(Allctr_t *allctr, Block_t *old_blk, Uint umem_sz, UWord flags)
new_crr_sz = new_blk_sz + SBC_HEADER_SIZE;
new_crr_sz = ERTS_SACRR_UNIT_CEILING(new_crr_sz);
- new_crr = (Carrier_t *) alcu_mseg_realloc(allctr,
+ new_crr = (Carrier_t *) allctr->mseg_realloc(allctr,
old_crr,
old_crr_sz,
&new_crr_sz);
@@ -3758,7 +3990,7 @@ resize_carrier(Allctr_t *allctr, Block_t *old_blk, Uint umem_sz, UWord flags)
(void *) BLK2UMEM(old_blk),
MIN(new_blk_sz, old_blk_sz) - ABLK_HDR_SZ);
unlink_carrier(&allctr->sbc_list, old_crr);
- alcu_mseg_dealloc(allctr, old_crr, old_crr_sz, ERTS_MSEG_FLG_NONE);
+ allctr->mseg_dealloc(allctr, old_crr, old_crr_sz, ERTS_MSEG_FLG_NONE);
}
else {
/* Old carrier unchanged; restore stat */
@@ -3775,7 +4007,7 @@ resize_carrier(Allctr_t *allctr, Block_t *old_blk, Uint umem_sz, UWord flags)
? UNIT_CEILING(new_bcrr_sz)
: SYS_ALLOC_CARRIER_CEILING(new_bcrr_sz));
- new_crr = (Carrier_t *) alcu_sys_realloc(allctr,
+ new_crr = (Carrier_t *) allctr->sys_realloc(allctr,
(void *) old_crr,
new_crr_sz,
old_crr_sz,
@@ -3796,7 +4028,7 @@ resize_carrier(Allctr_t *allctr, Block_t *old_blk, Uint umem_sz, UWord flags)
else if (new_crr_sz > UNIT_CEILING(new_bcrr_sz)) {
new_crr_sz = new_blk_sz + SBC_HEADER_SIZE;
new_crr_sz = UNIT_CEILING(new_crr_sz);
- new_crr = (Carrier_t *) alcu_sys_realloc(allctr,
+ new_crr = (Carrier_t *) allctr->sys_realloc(allctr,
(void *) old_crr,
new_crr_sz,
old_crr_sz,
@@ -3819,7 +4051,7 @@ resize_carrier(Allctr_t *allctr, Block_t *old_blk, Uint umem_sz, UWord flags)
(void *) BLK2UMEM(old_blk),
MIN(new_blk_sz, old_blk_sz) - ABLK_HDR_SZ);
unlink_carrier(&allctr->sbc_list, old_crr);
- alcu_sys_free(allctr, old_crr, 0);
+ allctr->sys_dealloc(allctr, old_crr, CARRIER_SZ(old_crr), 0);
}
else {
/* Old carrier unchanged; restore... */
@@ -3835,13 +4067,13 @@ dealloc_carrier(Allctr_t *allctr, Carrier_t *crr, int superaligned)
{
#if HAVE_ERTS_MSEG
if (IS_MSEG_CARRIER(crr))
- alcu_mseg_dealloc(allctr, crr, CARRIER_SZ(crr),
+ allctr->mseg_dealloc(allctr, crr, CARRIER_SZ(crr),
(superaligned
? ERTS_MSEG_FLG_2POW
: ERTS_MSEG_FLG_NONE));
else
#endif
- alcu_sys_free(allctr, crr, superaligned);
+ allctr->sys_dealloc(allctr, crr, CARRIER_SZ(crr), superaligned);
}
static void
@@ -3888,9 +4120,6 @@ destroy_carrier(Allctr_t *allctr, Block_t *blk, Carrier_t **busy_pcrr_pp)
}
#endif
- if (allctr->destroying_mbc)
- (*allctr->destroying_mbc)(allctr, crr);
-
#ifdef ERTS_SMP
if (busy_pcrr_pp && *busy_pcrr_pp) {
ERTS_ALC_CPOOL_ASSERT(*busy_pcrr_pp == crr);
@@ -3914,12 +4143,15 @@ destroy_carrier(Allctr_t *allctr, Block_t *blk, Carrier_t **busy_pcrr_pp)
else
#endif
STAT_SYS_ALLOC_MBC_FREE(allctr, crr_sz);
+
+ if (allctr->remove_mbc)
+ allctr->remove_mbc(allctr, crr);
}
#ifdef ERTS_SMP
schedule_dealloc_carrier(allctr, crr);
#else
- dealloc_carrier(allctr, crr, 1);
+ dealloc_mbc(allctr, crr);
#endif
}
}
@@ -5839,17 +6071,52 @@ erts_alcu_start(Allctr_t *allctr, AllctrInit_t *init)
+ ABLK_HDR_SZ)
- ABLK_HDR_SZ);
+ if (init->sys_alloc) {
+ ASSERT(init->sys_realloc && init->sys_dealloc);
+ allctr->sys_alloc = init->sys_alloc;
+ allctr->sys_realloc = init->sys_realloc;
+ allctr->sys_dealloc = init->sys_dealloc;
+ }
+ else {
+ ASSERT(!init->sys_realloc && !init->sys_dealloc);
+ allctr->sys_alloc = &erts_alcu_sys_alloc;
+ allctr->sys_realloc = &erts_alcu_sys_realloc;
+ allctr->sys_dealloc = &erts_alcu_sys_dealloc;
+ }
+#if HAVE_ERTS_MSEG
+ if (init->mseg_alloc) {
+ ASSERT(init->mseg_realloc && init->mseg_dealloc);
+ allctr->mseg_alloc = init->mseg_alloc;
+ allctr->mseg_realloc = init->mseg_realloc;
+ allctr->mseg_dealloc = init->mseg_dealloc;
+ }
+ else {
+ ASSERT(!init->mseg_realloc && !init->mseg_dealloc);
+ allctr->mseg_alloc = &erts_alcu_mseg_alloc;
+ allctr->mseg_realloc = &erts_alcu_mseg_realloc;
+ allctr->mseg_dealloc = &erts_alcu_mseg_dealloc;
+ }
+ /* If a custom carrier alloc function is specified, make sure it's used */
+ if (init->mseg_alloc && !init->sys_alloc) {
+ allctr->crr_set_flgs = CFLG_FORCE_MSEG;
+ allctr->crr_clr_flgs = CFLG_FORCE_SYS_ALLOC;
+ }
+ else if (!init->mseg_alloc && init->sys_alloc) {
+ allctr->crr_set_flgs = CFLG_FORCE_SYS_ALLOC;
+ allctr->crr_clr_flgs = CFLG_FORCE_MSEG;
+ }
+#endif
+
if (allctr->main_carrier_size) {
Block_t *blk;
blk = create_carrier(allctr,
allctr->main_carrier_size,
- CFLG_MBC
+ (ERTS_SUPER_ALIGNED_MSEG_ONLY
+ ? CFLG_FORCE_MSEG : CFLG_FORCE_SYS_ALLOC)
+ | CFLG_MBC
| CFLG_FORCE_SIZE
| CFLG_NO_CPOOL
-#if !ERTS_SUPER_ALIGNED_MSEG_ONLY
- | CFLG_FORCE_SYS_ALLOC
-#endif
| CFLG_MAIN_CARRIER);
if (!blk) {
#ifdef USE_THREADS
@@ -6026,6 +6293,16 @@ erts_alcu_test(UWord op, UWord a1, UWord a2)
case 0x023: return (UWord) 0;
case 0x024: return (UWord) 0;
#endif
+ case 0x025: /* UMEM2BLK_TEST*/
+#ifdef DEBUG
+# ifdef HARD_DEBUG
+ return (UWord)UMEM2BLK(a1-3*sizeof(UWord));
+# else
+ return (UWord)UMEM2BLK(a1-2*sizeof(UWord));
+# endif
+#else
+ return (UWord)UMEM2BLK(a1);
+#endif
default: ASSERT(0); return ~((UWord) 0);
}
diff --git a/erts/emulator/beam/erl_alloc_util.h b/erts/emulator/beam/erl_alloc_util.h
index 792f8c63ac..b7d717ed23 100644
--- a/erts/emulator/beam/erl_alloc_util.h
+++ b/erts/emulator/beam/erl_alloc_util.h
@@ -24,6 +24,12 @@
#define ERTS_ALCU_VSN_STR "3.0"
#include "erl_alloc_types.h"
+#ifdef USE_THREADS
+#define ERL_THREADS_EMU_INTERNAL__
+#include "erl_threads.h"
+#endif
+
+#include "erl_mseg.h"
#define ERTS_AU_PREF_ALLOC_BITS 11
#define ERTS_AU_MAX_PREF_ALLOC_INSTANCES (1 << ERTS_AU_PREF_ALLOC_BITS)
@@ -60,6 +66,15 @@ typedef struct {
void *fix;
size_t *fix_type_size;
+
+#if HAVE_ERTS_MSEG
+ void* (*mseg_alloc)(Allctr_t*, Uint *size_p, Uint flags);
+ void* (*mseg_realloc)(Allctr_t*, void *seg, Uint old_size, Uint *new_size_p);
+ void (*mseg_dealloc)(Allctr_t*, void *seg, Uint size, Uint flags);
+#endif
+ void* (*sys_alloc)(Allctr_t *allctr, Uint size, int superalign);
+ void* (*sys_realloc)(Allctr_t *allctr, void *ptr, Uint size, Uint old_size, int superalign);
+ void (*sys_dealloc)(Allctr_t *allctr, void *ptr, Uint size, int superalign);
} AllctrInit_t;
typedef struct {
@@ -173,20 +188,44 @@ void erts_alcu_check_delayed_dealloc(Allctr_t *, int, int *, ErtsThrPrgrVal *
#endif
erts_aint32_t erts_alcu_fix_alloc_shrink(Allctr_t *, erts_aint32_t);
+#ifdef ARCH_32
+extern UWord erts_literal_vspace_map[];
+# define ERTS_VSPACE_WORD_BITS (sizeof(UWord)*8)
+#endif
+
+void* erts_alcu_mseg_alloc(Allctr_t*, Uint *size_p, Uint flags);
+void* erts_alcu_mseg_realloc(Allctr_t*, void *seg, Uint old_size, Uint *new_size_p);
+void erts_alcu_mseg_dealloc(Allctr_t*, void *seg, Uint size, Uint flags);
+
+#if HAVE_ERTS_MSEG
+# if defined(ARCH_32)
+void* erts_alcu_literal_32_mseg_alloc(Allctr_t*, Uint *size_p, Uint flags);
+void* erts_alcu_literal_32_mseg_realloc(Allctr_t*, void *seg, Uint old_size, Uint *new_size_p);
+void erts_alcu_literal_32_mseg_dealloc(Allctr_t*, void *seg, Uint size, Uint flags);
+
+# elif defined(ARCH_64) && defined(ERTS_HAVE_OS_PHYSICAL_MEMORY_RESERVATION)
+void* erts_alcu_literal_64_mseg_alloc(Allctr_t*, Uint *size_p, Uint flags);
+void* erts_alcu_literal_64_mseg_realloc(Allctr_t*, void *seg, Uint old_size, Uint *new_size_p);
+void erts_alcu_literal_64_mseg_dealloc(Allctr_t*, void *seg, Uint size, Uint flags);
+# endif
+#endif /* HAVE_ERTS_MSEG */
+
+void* erts_alcu_sys_alloc(Allctr_t*, Uint size, int superalign);
+void* erts_alcu_sys_realloc(Allctr_t*, void *ptr, Uint size, Uint old_size, int superalign);
+void erts_alcu_sys_dealloc(Allctr_t*, void *ptr, Uint size, int superalign);
+#ifdef ARCH_32
+void* erts_alcu_literal_32_sys_alloc(Allctr_t*, Uint size, int superalign);
+void* erts_alcu_literal_32_sys_realloc(Allctr_t*, void *ptr, Uint size, Uint old_size, int superalign);
+void erts_alcu_literal_32_sys_dealloc(Allctr_t*, void *ptr, Uint size, int superalign);
#endif
+#endif /* !ERL_ALLOC_UTIL__ */
+
#if defined(GET_ERL_ALLOC_UTIL_IMPL) && !defined(ERL_ALLOC_UTIL_IMPL__)
#define ERL_ALLOC_UTIL_IMPL__
#define ERTS_ALCU_FLG_FAIL_REALLOC_MOVE (((Uint32) 1) << 0)
-#ifdef USE_THREADS
-#define ERL_THREADS_EMU_INTERNAL__
-#include "erl_threads.h"
-#endif
-
-#include "erl_mseg.h"
-
#undef ERTS_ALLOC_UTIL_HARD_DEBUG
#ifdef DEBUG
# if 0
@@ -220,7 +259,7 @@ erts_aint32_t erts_alcu_fix_alloc_shrink(Allctr_t *, erts_aint32_t);
#if ERTS_HAVE_MSEG_SUPER_ALIGNED \
|| (!HAVE_ERTS_MSEG && ERTS_HAVE_ERTS_SYS_ALIGNED_ALLOC)
-# ifndef MSEG_ALIGN_BITS
+# ifdef MSEG_ALIGN_BITS
# define ERTS_SUPER_ALIGN_BITS MSEG_ALIGN_BITS
# else
# define ERTS_SUPER_ALIGN_BITS 18
@@ -274,7 +313,7 @@ typedef struct ErtsDoubleLink_t_ {
typedef struct {
erts_atomic_t next;
erts_atomic_t prev;
- Allctr_t *orig_allctr;
+ Allctr_t *orig_allctr; /* read-only while carrier is alive */
ErtsThrPrgrVal thr_prgr;
erts_atomic_t max_size;
UWord abandon_limit;
@@ -498,6 +537,8 @@ struct Allctr_t_ {
Uint min_mbc_size;
Uint min_mbc_first_free_size;
Uint min_block_size;
+ UWord crr_set_flgs;
+ UWord crr_clr_flgs;
/* Carriers */
CarrierList_t mbc_list;
@@ -543,6 +584,15 @@ struct Allctr_t_ {
void (*remove_mbc) (Allctr_t *, Carrier_t *);
UWord (*largest_fblk_in_mbc) (Allctr_t *, Carrier_t *);
+#if HAVE_ERTS_MSEG
+ void* (*mseg_alloc)(Allctr_t*, Uint *size_p, Uint flags);
+ void* (*mseg_realloc)(Allctr_t*, void *seg, Uint old_size, Uint *new_size_p);
+ void (*mseg_dealloc)(Allctr_t*, void *seg, Uint size, Uint flags);
+#endif
+ void* (*sys_alloc)(Allctr_t *allctr, Uint size, int superalign);
+ void* (*sys_realloc)(Allctr_t *allctr, void *ptr, Uint size, Uint old_size, int superalign);
+ void (*sys_dealloc)(Allctr_t *allctr, void *ptr, Uint size, int superalign);
+
void (*init_atoms) (void);
#ifdef ERTS_ALLOC_UTIL_HARD_DEBUG
diff --git a/erts/emulator/beam/erl_ao_firstfit_alloc.c b/erts/emulator/beam/erl_ao_firstfit_alloc.c
index 7c2a5c3323..19420af8ab 100644
--- a/erts/emulator/beam/erl_ao_firstfit_alloc.c
+++ b/erts/emulator/beam/erl_ao_firstfit_alloc.c
@@ -209,7 +209,9 @@ static Block_t* aoff_get_free_block(Allctr_t *, Uint, Block_t *, Uint);
static void aoff_link_free_block(Allctr_t *, Block_t*);
static void aoff_unlink_free_block(Allctr_t *allctr, Block_t *del);
static void aoff_creating_mbc(Allctr_t*, Carrier_t*);
+#ifdef DEBUG
static void aoff_destroying_mbc(Allctr_t*, Carrier_t*);
+#endif
static void aoff_add_mbc(Allctr_t*, Carrier_t*);
static void aoff_remove_mbc(Allctr_t*, Carrier_t*);
static UWord aoff_largest_fblk_in_mbc(Allctr_t*, Carrier_t*);
@@ -271,7 +273,11 @@ erts_aoffalc_start(AOFFAllctr_t *alc,
allctr->get_next_mbc_size = NULL;
allctr->creating_mbc = aoff_creating_mbc;
+#ifdef DEBUG
allctr->destroying_mbc = aoff_destroying_mbc;
+#else
+ allctr->destroying_mbc = NULL;
+#endif
allctr->add_mbc = aoff_add_mbc;
allctr->remove_mbc = aoff_remove_mbc;
allctr->largest_fblk_in_mbc = aoff_largest_fblk_in_mbc;
@@ -885,17 +891,18 @@ static void aoff_creating_mbc(Allctr_t *allctr, Carrier_t *carrier)
HARD_CHECK_TREE(NULL, 0, *root, 0);
}
+#define IS_CRR_IN_TREE(CRR,ROOT) \
+ ((CRR)->rbt_node.parent || (ROOT) == &(CRR)->rbt_node)
+
+#ifdef DEBUG
static void aoff_destroying_mbc(Allctr_t *allctr, Carrier_t *carrier)
{
AOFFAllctr_t *alc = (AOFFAllctr_t *) allctr;
AOFF_Carrier_t *crr = (AOFF_Carrier_t*) carrier;
- AOFF_RBTree_t *root = alc->mbc_root;
- if (crr->rbt_node.parent || &crr->rbt_node == root) {
- aoff_remove_mbc(allctr, carrier);
- }
- /*else already removed */
+ ASSERT(!IS_CRR_IN_TREE(crr, alc->mbc_root));
}
+#endif
static void aoff_add_mbc(Allctr_t *allctr, Carrier_t *carrier)
{
@@ -903,6 +910,7 @@ static void aoff_add_mbc(Allctr_t *allctr, Carrier_t *carrier)
AOFF_Carrier_t *crr = (AOFF_Carrier_t*) carrier;
AOFF_RBTree_t **root = &alc->mbc_root;
+ ASSERT(!IS_CRR_IN_TREE(crr, *root));
HARD_CHECK_TREE(NULL, 0, *root, 0);
/* Link carrier in address order tree
@@ -919,6 +927,10 @@ static void aoff_remove_mbc(Allctr_t *allctr, Carrier_t *carrier)
AOFF_RBTree_t **root = &alc->mbc_root;
ASSERT(allctr == ERTS_ALC_CARRIER_TO_ALLCTR(carrier));
+
+ if (!IS_CRR_IN_TREE(crr,*root))
+ return;
+
HARD_CHECK_TREE(NULL, 0, *root, 0);
rbt_delete(root, &crr->rbt_node);
diff --git a/erts/emulator/beam/erl_bif_binary.c b/erts/emulator/beam/erl_bif_binary.c
index b9640e211d..aec72bd61a 100644
--- a/erts/emulator/beam/erl_bif_binary.c
+++ b/erts/emulator/beam/erl_bif_binary.c
@@ -1614,6 +1614,10 @@ static Eterm do_split_not_found_result(Process *p, Eterm subject, BinaryFindStat
Eterm *hp;
Eterm ret;
+ if (bfs->flags & (BINARY_SPLIT_TRIM | BINARY_SPLIT_TRIM_ALL)
+ && binary_size(subject) == 0) {
+ return NIL;
+ }
hp = HAlloc(p, 2);
ret = CONS(hp, subject, NIL);
diff --git a/erts/emulator/beam/erl_bif_ddll.c b/erts/emulator/beam/erl_bif_ddll.c
index 28bec6325c..2b1d875bfe 100644
--- a/erts/emulator/beam/erl_bif_ddll.c
+++ b/erts/emulator/beam/erl_bif_ddll.c
@@ -1707,18 +1707,19 @@ static void notify_proc(Process *proc, Eterm ref, Eterm driver_name, Eterm type,
Eterm mess;
Eterm r;
Eterm *hp;
- ErlHeapFragment *bp;
- ErlOffHeap *ohp;
+ ErtsMessage *mp;
ErtsProcLocks rp_locks = 0;
+ ErlOffHeap *ohp;
ERTS_SMP_CHK_NO_PROC_LOCKS;
assert_drv_list_rwlocked();
if (errcode != 0) {
int need = load_error_need(errcode);
Eterm e;
- hp = erts_alloc_message_heap(6 /* tuple */ + 3 /* Error tuple */ +
- REF_THING_SIZE + need, &bp, &ohp,
- proc, &rp_locks);
+ mp = erts_alloc_message_heap(proc, &rp_locks,
+ (6 /* tuple */ + 3 /* Error tuple */ +
+ REF_THING_SIZE + need),
+ &hp, &ohp);
r = copy_ref(ref,hp);
hp += REF_THING_SIZE;
e = build_load_error_hp(hp, errcode);
@@ -1727,12 +1728,14 @@ static void notify_proc(Process *proc, Eterm ref, Eterm driver_name, Eterm type,
hp += 3;
mess = TUPLE5(hp,type,r,am_driver,driver_name,mess);
} else {
- hp = erts_alloc_message_heap(6 /* tuple */ + REF_THING_SIZE, &bp, &ohp, proc, &rp_locks);
+ mp = erts_alloc_message_heap(proc, &rp_locks,
+ 6 /* tuple */ + REF_THING_SIZE,
+ &hp, &ohp);
r = copy_ref(ref,hp);
hp += REF_THING_SIZE;
mess = TUPLE5(hp,type,r,am_driver,driver_name,tag);
}
- erts_queue_message(proc, &rp_locks, bp, mess, am_undefined);
+ erts_queue_message(proc, &rp_locks, mp, mess, am_undefined);
erts_smp_proc_unlock(proc, rp_locks);
ERTS_SMP_CHK_NO_PROC_LOCKS;
}
diff --git a/erts/emulator/beam/erl_bif_info.c b/erts/emulator/beam/erl_bif_info.c
index 9a132ee007..f952f937ce 100644
--- a/erts/emulator/beam/erl_bif_info.c
+++ b/erts/emulator/beam/erl_bif_info.c
@@ -130,6 +130,9 @@ static char erts_system_version[] = ("Erlang/OTP " ERLANG_OTP_RELEASE
#ifdef USE_SYSTEMTAP
" [systemtap]"
#endif
+#ifdef SHCOPY
+ " [sharing-preserving]"
+#endif
"\n");
#define ASIZE(a) (sizeof(a)/sizeof(a[0]))
@@ -589,6 +592,7 @@ static Eterm pi_args[] = {
am_min_bin_vheap_size,
am_current_location,
am_current_stacktrace,
+ am_message_queue_data
};
#define ERTS_PI_ARGS ((int) (sizeof(pi_args)/sizeof(Eterm)))
@@ -636,6 +640,7 @@ pi_arg2ix(Eterm arg)
case am_min_bin_vheap_size: return 28;
case am_current_location: return 29;
case am_current_stacktrace: return 30;
+ case am_message_queue_data: return 31;
default: return -1;
}
}
@@ -718,9 +723,10 @@ pi_pid2proc(Process *c_p, Eterm pid, ErtsProcLocks info_locks)
-BIF_RETTYPE
+static BIF_RETTYPE
process_info_aux(Process *BIF_P,
Process *rp,
+ ErtsProcLocks rp_locks,
Eterm rpid,
Eterm item,
int always_wrap);
@@ -811,10 +817,31 @@ process_info_list(Process *c_p, Eterm pid, Eterm list, int always_wrap,
*fail_type = ERTS_PI_FAIL_TYPE_AWAIT_EXIT;
goto done;
}
- else if (!(locks & ERTS_PROC_LOCK_STATUS)) {
- erts_smp_proc_unlock(rp, ERTS_PROC_LOCK_STATUS);
+ else {
+ ErtsProcLocks unlock_locks = 0;
+
+ if (c_p == rp)
+ locks |= ERTS_PROC_LOCK_MAIN;
+
+ if (!(locks & ERTS_PROC_LOCK_STATUS))
+ unlock_locks |= ERTS_PROC_LOCK_STATUS;
+
+ if (locks & ERTS_PROC_LOCK_MSGQ) {
+ /*
+ * Move in queue into private queue and
+ * release msgq lock, enabling others to
+ * send messages to the process while it
+ * is being inspected...
+ */
+ ASSERT(locks & ERTS_PROC_LOCK_MAIN);
+ ERTS_SMP_MSGQ_MV_INQ2PRIVQ(rp);
+ locks &= ~ERTS_PROC_LOCK_MSGQ;
+ unlock_locks |= ERTS_PROC_LOCK_MSGQ;
+ }
+
+ if (unlock_locks)
+ erts_smp_proc_unlock(rp, unlock_locks);
}
-
/*
* We always handle 'messages' first if it should be part
@@ -826,7 +853,7 @@ process_info_list(Process *c_p, Eterm pid, Eterm list, int always_wrap,
if (want_messages) {
ix = pi_arg2ix(am_messages);
ASSERT(part_res[ix] == THE_NON_VALUE);
- part_res[ix] = process_info_aux(c_p, rp, pid, am_messages, always_wrap);
+ part_res[ix] = process_info_aux(c_p, rp, locks, pid, am_messages, always_wrap);
ASSERT(part_res[ix] != THE_NON_VALUE);
}
@@ -834,7 +861,7 @@ process_info_list(Process *c_p, Eterm pid, Eterm list, int always_wrap,
ix = res_elem_ix[res_elem_ix_ix];
if (part_res[ix] == THE_NON_VALUE) {
arg = pi_ix2arg(ix);
- part_res[ix] = process_info_aux(c_p, rp, pid, arg, always_wrap);
+ part_res[ix] = process_info_aux(c_p, rp, locks, pid, arg, always_wrap);
ASSERT(part_res[ix] != THE_NON_VALUE);
}
}
@@ -965,9 +992,31 @@ BIF_RETTYPE process_info_2(BIF_ALIST_2)
ERTS_BIF_AWAIT_X_DATA_TRAP(BIF_P, BIF_ARG_1, am_undefined);
}
else {
+ ErtsProcLocks unlock_locks = 0;
+
+ if (BIF_P == rp)
+ info_locks |= ERTS_PROC_LOCK_MAIN;
+
if (!(info_locks & ERTS_PROC_LOCK_STATUS))
- erts_smp_proc_unlock(rp, ERTS_PROC_LOCK_STATUS);
- res = process_info_aux(BIF_P, rp, pid, BIF_ARG_2, 0);
+ unlock_locks |= ERTS_PROC_LOCK_STATUS;
+
+ if (info_locks & ERTS_PROC_LOCK_MSGQ) {
+ /*
+ * Move in queue into private queue and
+ * release msgq lock, enabling others to
+ * send messages to the process while it
+ * is being inspected...
+ */
+ ASSERT(info_locks & ERTS_PROC_LOCK_MAIN);
+ ERTS_SMP_MSGQ_MV_INQ2PRIVQ(rp);
+ info_locks &= ~ERTS_PROC_LOCK_MSGQ;
+ unlock_locks |= ERTS_PROC_LOCK_MSGQ;
+ }
+
+ if (unlock_locks)
+ erts_smp_proc_unlock(rp, unlock_locks);
+
+ res = process_info_aux(BIF_P, rp, info_locks, pid, BIF_ARG_2, 0);
}
ASSERT(is_value(res));
@@ -985,6 +1034,7 @@ BIF_RETTYPE process_info_2(BIF_ALIST_2)
Eterm
process_info_aux(Process *BIF_P,
Process *rp,
+ ErtsProcLocks rp_locks,
Eterm rpid,
Eterm item,
int always_wrap)
@@ -1056,171 +1106,55 @@ process_info_aux(Process *BIF_P,
break;
case am_messages: {
- ErlMessage* mp;
- int n;
-
- ERTS_SMP_MSGQ_MV_INQ2PRIVQ(rp);
- n = rp->msg.len;
- if (n == 0 || ERTS_TRACE_FLAGS(rp) & F_SENSITIVE) {
+ if (rp->msg.len == 0 || ERTS_TRACE_FLAGS(rp) & F_SENSITIVE) {
hp = HAlloc(BIF_P, 3);
} else {
- int remove_bad_messages = 0;
- struct {
- Uint copy_struct_size;
- ErlMessage* msgp;
- } *mq = erts_alloc(ERTS_ALC_T_TMP, n*sizeof(*mq));
- Sint i = 0;
- Uint heap_need = 3;
+ ErtsMessageInfo *mip;
+ Sint i;
+ Uint heap_need;
+#ifdef DEBUG
Eterm *hp_end;
+#endif
- for (mp = rp->msg.first; mp; mp = mp->next) {
- heap_need += 2;
- mq[i].msgp = mp;
- if (rp != BIF_P) {
- Eterm msg = ERL_MESSAGE_TERM(mq[i].msgp);
- if (is_value(msg)) {
- mq[i].copy_struct_size = (is_immed(msg)? 0 :
- size_object(msg));
- }
- else if (mq[i].msgp->data.attached) {
- mq[i].copy_struct_size
- = erts_msg_attached_data_size(mq[i].msgp);
- }
- else {
- /* Bad distribution message; ignore */
- remove_bad_messages = 1;
- mq[i].copy_struct_size = 0;
- }
- heap_need += mq[i].copy_struct_size;
- }
- else {
- mq[i].copy_struct_size = mp->data.attached ?
- erts_msg_attached_data_size(mp) : 0;
- }
- i++;
- }
+ mip = erts_alloc(ERTS_ALC_T_TMP,
+ rp->msg.len*sizeof(ErtsMessageInfo));
- if (rp != BIF_P) {
- hp = HAlloc(BIF_P, heap_need);
- hp_end = hp + heap_need;
- ASSERT(i == n);
- for (i--; i >= 0; i--) {
- Eterm msg = ERL_MESSAGE_TERM(mq[i].msgp);
- if (is_value(msg)) {
- if (mq[i].copy_struct_size)
- msg = copy_struct(msg,
- mq[i].copy_struct_size,
- &hp,
- &MSO(BIF_P));
- }
- else if (mq[i].msgp->data.attached) {
- ErlHeapFragment *hfp;
- /*
- * Decode it into a message buffer and attach it
- * to the message instead of the attached external
- * term.
- *
- * Note that we may not pass a process pointer
- * to erts_msg_distext2heap(), since it would then
- * try to alter locks on that process.
- */
- msg = erts_msg_distext2heap(
- NULL, NULL, &hfp, &ERL_MESSAGE_TOKEN(mq[i].msgp),
- mq[i].msgp->data.dist_ext);
-
- ERL_MESSAGE_TERM(mq[i].msgp) = msg;
- mq[i].msgp->data.heap_frag = hfp;
-
- if (is_non_value(msg)) {
- ASSERT(!mq[i].msgp->data.heap_frag);
- /* Bad distribution message; ignore */
- remove_bad_messages = 1;
- continue;
- }
- else {
- /* Make our copy of the message */
- ASSERT(size_object(msg) == erts_used_frag_sz(hfp));
- msg = copy_struct(msg,
- erts_used_frag_sz(hfp),
- &hp,
- &MSO(BIF_P));
- }
- }
- else {
- /* Bad distribution message; ignore */
- remove_bad_messages = 1;
- continue;
- }
- res = CONS(hp, msg, res);
- hp += 2;
- }
- HRelease(BIF_P, hp_end, hp+3);
- }
- else {
- for (i--; i >= 0; i--) {
- ErtsHeapFactory factory;
- Eterm msg = ERL_MESSAGE_TERM(mq[i].msgp);
-
- erts_factory_proc_prealloc_init(&factory, BIF_P,
- mq[i].copy_struct_size+2);
- if (mq[i].msgp->data.attached) {
- /* Decode it on the heap */
- erts_move_msg_attached_data_to_heap(&factory,
- mq[i].msgp);
- msg = ERL_MESSAGE_TERM(mq[i].msgp);
- ASSERT(!mq[i].msgp->data.attached);
- }
- if (is_value(msg)) {
- hp = erts_produce_heap(&factory, 2, 0);
- res = CONS(hp, msg, res);
- }
- else {
- /* Bad distribution message; ignore */
- remove_bad_messages = 1;
- continue;
- }
- erts_factory_close(&factory);
- }
- hp = HAlloc(BIF_P, 3);
- }
- erts_free(ERTS_ALC_T_TMP, mq);
- if (remove_bad_messages) {
- ErlMessage **mpp;
- /*
- * We need to remove bad distribution messages from
- * the queue, so that the value returned for
- * 'message_queue_len' is consistent with the value
- * returned for 'messages'.
- */
- mpp = &rp->msg.first;
- mp = rp->msg.first;
- while (mp) {
- if (is_value(ERL_MESSAGE_TERM(mp))) {
- mpp = &mp->next;
- mp = mp->next;
- }
- else {
- ErlMessage* bad_mp = mp;
- ASSERT(!mp->data.attached);
- if (rp->msg.save == &mp->next)
- rp->msg.save = mpp;
- if (rp->msg.last == &mp->next)
- rp->msg.last = mpp;
- *mpp = mp->next;
- mp = mp->next;
- rp->msg.len--;
- free_message(bad_mp);
- }
- }
+ /*
+ * Note that message queue may shrink when calling
+ * erts_prep_msgq_for_inspection() since it removes
+ * corrupt distribution messages.
+ */
+ heap_need = erts_prep_msgq_for_inspection(BIF_P, rp, rp_locks, mip);
+ heap_need += 3; /* top 2-tuple */
+ heap_need += rp->msg.len*2; /* Cons cells */
+
+ hp = HAlloc(BIF_P, heap_need); /* heap_need is exact */
+#ifdef DEBUG
+ hp_end = hp + heap_need;
+#endif
+
+ /* Build list of messages... */
+ for (i = rp->msg.len - 1, res = NIL; i >= 0; i--) {
+ Eterm msg = ERL_MESSAGE_TERM(mip[i].msgp);
+ Uint sz = mip[i].size;
+
+ if (sz != 0)
+ msg = copy_struct(msg, sz, &hp, &BIF_P->off_heap);
+
+ res = CONS(hp, msg, res);
+ hp += 2;
}
+
+ ASSERT(hp_end == hp + 3);
+
+ erts_free(ERTS_ALC_T_TMP, mip);
}
break;
}
case am_message_queue_len:
hp = HAlloc(BIF_P, 3);
- ERTS_SMP_MSGQ_MV_INQ2PRIVQ(rp);
res = make_small(rp->msg.len);
break;
@@ -1408,7 +1342,7 @@ process_info_aux(Process *BIF_P,
}
case am_total_heap_size: {
- ErlMessage *mp;
+ ErtsMessage *mp;
Uint total_heap_size;
Uint hsz = 3;
@@ -1418,8 +1352,6 @@ process_info_aux(Process *BIF_P,
total_heap_size += rp->mbuf_sz;
- ERTS_SMP_MSGQ_MV_INQ2PRIVQ(rp);
-
for (mp = rp->msg.first; mp; mp = mp->next)
if (mp->data.attached)
total_heap_size += erts_msg_attached_data_size(mp);
@@ -1441,7 +1373,7 @@ process_info_aux(Process *BIF_P,
case am_memory: { /* Memory consumed in bytes */
Uint hsz = 3;
- Uint size = erts_process_memory(rp);
+ Uint size = erts_process_memory(rp, 0);
(void) erts_bld_uint(NULL, &hsz, size);
hp = HAlloc(BIF_P, hsz);
res = erts_bld_uint(&hp, NULL, size);
@@ -1567,6 +1499,25 @@ process_info_aux(Process *BIF_P,
break;
}
+ case am_message_queue_data:
+ switch (rp->flags & (F_OFF_HEAP_MSGQ|F_ON_HEAP_MSGQ)) {
+ case F_OFF_HEAP_MSGQ:
+ res = am_off_heap;
+ break;
+ case F_ON_HEAP_MSGQ:
+ res = am_on_heap;
+ break;
+ case 0:
+ res = am_mixed;
+ break;
+ default:
+ res = am_error;
+ ERTS_INTERNAL_ERROR("Inconsistent message queue management state");
+ break;
+ }
+ hp = HAlloc(BIF_P, 3);
+ break;
+
default:
return THE_NON_VALUE; /* will produce badarg */
@@ -2728,6 +2679,19 @@ BIF_RETTYPE system_info_1(BIF_ALIST_1)
BIF_RET(am_true);
}
#endif
+ else if (BIF_ARG_1 == am_message_queue_data) {
+ switch (erts_default_spo_flags & (SPO_ON_HEAP_MSGQ|SPO_OFF_HEAP_MSGQ)) {
+ case SPO_OFF_HEAP_MSGQ:
+ BIF_RET(am_off_heap);
+ case SPO_ON_HEAP_MSGQ:
+ BIF_RET(am_on_heap);
+ case 0:
+ BIF_RET(am_mixed);
+ default:
+ ERTS_INTERNAL_ERROR("Inconsistent message queue management state");
+ BIF_RET(am_error);
+ }
+ }
else if (ERTS_IS_ATOM_STR("compile_info",BIF_ARG_1)) {
Uint sz;
Eterm res = NIL, tup, text;
@@ -2766,6 +2730,20 @@ BIF_RETTYPE system_info_1(BIF_ALIST_1)
else if (ERTS_IS_ATOM_STR("eager_check_io",BIF_ARG_1)) {
BIF_RET(erts_eager_check_io ? am_true : am_false);
}
+ else if (ERTS_IS_ATOM_STR("literal_test",BIF_ARG_1)) {
+#ifdef ERTS_HAVE_IS_IN_LITERAL_RANGE
+#ifdef ARCH_64
+ DECL_AM(range);
+ BIF_RET(AM_range);
+#else /* ARCH_32 */
+ DECL_AM(range_bitmask);
+ BIF_RET(AM_range_bitmask);
+#endif /* ARCH_32 */
+#else /* ! ERTS_HAVE_IS_IN_LITERAL_RANGE */
+ DECL_AM(tag);
+ BIF_RET(AM_tag);
+#endif
+ }
BIF_ERROR(BIF_P, BADARG);
}
@@ -3441,7 +3419,7 @@ BIF_RETTYPE erts_debug_get_internal_state_1(BIF_ALIST_1)
BIF_RET(res);
}
else if (ERTS_IS_ATOM_STR("mmap", BIF_ARG_1)) {
- BIF_RET(erts_mmap_debug_info(BIF_P));
+ BIF_RET(erts_mmap_debug_info(&erts_dflt_mmapper, BIF_P));
}
else if (ERTS_IS_ATOM_STR("unique_monotonic_integer_state", BIF_ARG_1)) {
BIF_RET(erts_debug_get_unique_monotonic_integer_state(BIF_P));
@@ -3851,9 +3829,7 @@ BIF_RETTYPE erts_debug_set_internal_state_2(BIF_ALIST_2)
BIF_RET(am_false);
}
else {
- FLAGS(rp) |= F_FORCE_GC;
- if (BIF_P != rp)
- erts_smp_proc_unlock(rp, ERTS_PROC_LOCK_MAIN);
+ ERTS_FORCE_GC(BIF_P);
BIF_RET(am_true);
}
}
@@ -4321,14 +4297,17 @@ static void os_info_init(void)
os_flavor(buf, 1024);
flav = erts_atom_put((byte *) buf, strlen(buf), ERTS_ATOM_ENC_LATIN1, 1);
erts_free(ERTS_ALC_T_TMP, (void *) buf);
- hp = erts_alloc(ERTS_ALC_T_LL_TEMP_TERM, (3+4)*sizeof(Eterm));
+ hp = erts_alloc(ERTS_ALC_T_LITERAL, (3+4)*sizeof(Eterm));
os_type_tuple = TUPLE2(hp, type, flav);
+ erts_set_literal_tag(&os_type_tuple, hp, 3);
+
hp += 3;
os_version(&major, &minor, &build);
os_version_tuple = TUPLE3(hp,
make_small(major),
make_small(minor),
make_small(build));
+ erts_set_literal_tag(&os_version_tuple, hp, 4);
}
void
diff --git a/erts/emulator/beam/erl_bif_trace.c b/erts/emulator/beam/erl_bif_trace.c
index 03f51132b1..4d67e39e7e 100644
--- a/erts/emulator/beam/erl_bif_trace.c
+++ b/erts/emulator/beam/erl_bif_trace.c
@@ -1879,11 +1879,7 @@ new_seq_trace_token(Process* p)
{
Eterm* hp;
- if (SEQ_TRACE_TOKEN(p) == NIL
-#ifdef USE_VM_PROBES
- || SEQ_TRACE_TOKEN(p) == am_have_dt_utag
-#endif
- ) {
+ if (have_no_seqtrace(SEQ_TRACE_TOKEN(p))) {
hp = HAlloc(p, 6);
SEQ_TRACE_TOKEN(p) = TUPLE5(hp, make_small(0), /* Flags */
make_small(0), /* Label */
@@ -1903,12 +1899,8 @@ BIF_RETTYPE erl_seq_trace_info(Process *p, Eterm item)
BIF_ERROR(p, BADARG);
}
- if (SEQ_TRACE_TOKEN(p) == NIL
-#ifdef USE_VM_PROBES
- || SEQ_TRACE_TOKEN(p) == am_have_dt_utag
-#endif
- ) {
- if ((item == am_send) || (item == am_receive) ||
+ if (have_no_seqtrace(SEQ_TRACE_TOKEN(p))) {
+ if ((item == am_send) || (item == am_receive) ||
(item == am_print) || (item == am_timestamp)) {
hp = HAlloc(p,3);
res = TUPLE2(hp, item, am_false);
@@ -1964,11 +1956,7 @@ BIF_RETTYPE seq_trace_info_1(BIF_ALIST_1)
*/
BIF_RETTYPE seq_trace_print_1(BIF_ALIST_1)
{
- if (SEQ_TRACE_TOKEN(BIF_P) == NIL
-#ifdef USE_VM_PROBES
- || SEQ_TRACE_TOKEN(BIF_P) == am_have_dt_utag
-#endif
- ) {
+ if (have_no_seqtrace(SEQ_TRACE_TOKEN(BIF_P))) {
BIF_RET(am_false);
}
seq_trace_update_send(BIF_P);
@@ -1987,11 +1975,7 @@ BIF_RETTYPE seq_trace_print_1(BIF_ALIST_1)
*/
BIF_RETTYPE seq_trace_print_2(BIF_ALIST_2)
{
- if (SEQ_TRACE_TOKEN(BIF_P) == NIL
-#ifdef USE_VM_PROBES
- || SEQ_TRACE_TOKEN(BIF_P) == am_have_dt_utag
-#endif
- ) {
+ if (have_no_seqtrace(SEQ_TRACE_TOKEN(BIF_P))) {
BIF_RET(am_false);
}
if (!(is_atom(BIF_ARG_1) || is_small(BIF_ARG_1))) {
diff --git a/erts/emulator/beam/erl_db.c b/erts/emulator/beam/erl_db.c
index 9ec14ab5ae..3030c1c91a 100644
--- a/erts/emulator/beam/erl_db.c
+++ b/erts/emulator/beam/erl_db.c
@@ -1832,7 +1832,7 @@ BIF_RETTYPE ets_give_away_3(BIF_ALIST_3)
tb->common.id,
from_pid,
BIF_ARG_3),
- 0);
+ 0);
erts_smp_proc_unlock(to_proc, to_locks);
UnUseTmpHeap(5,BIF_P);
BIF_RET(am_true);
@@ -3211,7 +3211,7 @@ retry:
tb->common.id,
p->common.id,
heir_data),
- 0);
+ 0);
erts_smp_proc_unlock(to_proc, to_locks);
return !0;
}
diff --git a/erts/emulator/beam/erl_db_util.c b/erts/emulator/beam/erl_db_util.c
index 0bf9558ac9..399be6058c 100644
--- a/erts/emulator/beam/erl_db_util.c
+++ b/erts/emulator/beam/erl_db_util.c
@@ -2308,11 +2308,7 @@ restart:
*esp++ = am_true;
break;
case matchIsSeqTrace:
- if (SEQ_TRACE_TOKEN(c_p) != NIL
-#ifdef USE_VM_PROBES
- && SEQ_TRACE_TOKEN(c_p) != am_have_dt_utag
-#endif
- )
+ if (have_seqtrace(SEQ_TRACE_TOKEN(c_p)))
*esp++ = am_true;
else
*esp++ = am_false;
@@ -2336,11 +2332,7 @@ restart:
--esp;
break;
case matchGetSeqToken:
- if (SEQ_TRACE_TOKEN(c_p) == NIL
-#ifdef USE_VM_PROBES
- || SEQ_TRACE_TOKEN(c_p) == am_have_dt_utag
-#endif
- )
+ if (have_no_seqtrace(SEQ_TRACE_TOKEN(c_p)))
*esp++ = NIL;
else {
Eterm sender = SEQ_TRACE_TOKEN_SENDER(c_p);
diff --git a/erts/emulator/beam/erl_debug.c b/erts/emulator/beam/erl_debug.c
index fae38728e4..49b08c8536 100644
--- a/erts/emulator/beam/erl_debug.c
+++ b/erts/emulator/beam/erl_debug.c
@@ -312,6 +312,8 @@ void erts_check_for_holes(Process* p)
p->last_htop = HEAP_TOP(p);
for (hf = MBUF(p); hf != 0; hf = hf->next) {
+ if (hf == p->heap_hfrag)
+ continue;
if (hf == p->last_mbuf) {
break;
}
@@ -402,7 +404,7 @@ void verify_process(Process *p)
erl_exit(1,"Wild pointer found in " name " of %T!\n",p->common.id); }
- ErlMessage* mp = p->msg.first;
+ ErtsMessage* mp = p->msg.first;
VERBOSE(DEBUG_MEMORY,("Verify process: %T...\n",p->common.id));
@@ -531,7 +533,7 @@ static void print_process_memory(Process *p)
PTR_SIZE, "PCB", dashes, dashes, dashes, dashes);
if (p->msg.first != NULL) {
- ErlMessage* mp;
+ ErtsMessage* mp;
erts_printf(" Message Queue:\n");
mp = p->msg.first;
while (mp != NULL) {
diff --git a/erts/emulator/beam/erl_debug.h b/erts/emulator/beam/erl_debug.h
index f4259e7dae..029320691d 100644
--- a/erts/emulator/beam/erl_debug.h
+++ b/erts/emulator/beam/erl_debug.h
@@ -48,6 +48,7 @@
#define DEBUG_THREADS 0x0010 /* Thread-related stuff */
#define DEBUG_PROCESSES 0x0020 /* Process creation and removal */
#define DEBUG_MEMORY 0x0040 /* Display results of memory checks */
+#define DEBUG_SHCOPY 0x0080 /* Sharing-preserving copying of terms */
extern Uint32 verbose;
diff --git a/erts/emulator/beam/erl_driver.h b/erts/emulator/beam/erl_driver.h
index ef7792ecab..bda4d5d1c6 100644
--- a/erts/emulator/beam/erl_driver.h
+++ b/erts/emulator/beam/erl_driver.h
@@ -688,8 +688,8 @@ EXTERN int driver_dl_close(void *);
EXTERN char *driver_dl_error(void);
/* environment */
-EXTERN int erl_drv_putenv(char *key, char *value);
-EXTERN int erl_drv_getenv(char *key, char *value, size_t *value_size);
+EXTERN int erl_drv_putenv(const char *key, char *value);
+EXTERN int erl_drv_getenv(const char *key, char *value, size_t *value_size);
/* spawn start init ack */
EXTERN void erl_drv_init_ack(ErlDrvPort ix, ErlDrvData res);
diff --git a/erts/emulator/beam/erl_gc.c b/erts/emulator/beam/erl_gc.c
index 29579f74e6..15226074c3 100644
--- a/erts/emulator/beam/erl_gc.c
+++ b/erts/emulator/beam/erl_gc.c
@@ -47,6 +47,17 @@
#define ERTS_INACT_WR_PB_LEAVE_LIMIT 10
#define ERTS_INACT_WR_PB_LEAVE_PERCENTAGE 10
+#if defined(DEBUG) || 0
+#define ERTS_GC_DEBUG
+#else
+#undef ERTS_GC_DEBUG
+#endif
+#ifdef ERTS_GC_DEBUG
+# define ERTS_GC_ASSERT ASSERT
+#else
+# define ERTS_GC_ASSERT(B) ((void) 1)
+#endif
+
/*
* Returns number of elements in an array.
*/
@@ -67,10 +78,10 @@
#define ErtsGcQuickSanityCheck(P) \
do { \
ASSERT((P)->heap < (P)->hend); \
- ASSERT((P)->heap_sz == (P)->hend - (P)->heap); \
+ ASSERT((p)->abandoned_heap || (P)->heap_sz == (P)->hend - (P)->heap); \
ASSERT((P)->heap <= (P)->htop && (P)->htop <= (P)->hend); \
ASSERT((P)->heap <= (P)->stop && (P)->stop <= (P)->hend); \
- ASSERT((P)->heap <= (P)->high_water && (P)->high_water <= (P)->hend);\
+ ASSERT((p)->abandoned_heap || ((P)->heap <= (P)->high_water && (P)->high_water <= (P)->hend)); \
OverRunCheck((P)); \
} while (0)
#else
@@ -98,18 +109,33 @@ typedef struct {
static Uint setup_rootset(Process*, Eterm*, int, Rootset*);
static void cleanup_rootset(Rootset *rootset);
-static Uint combined_message_size(Process* p);
static void remove_message_buffers(Process* p);
-static int major_collection(Process* p, int need, Eterm* objv, int nobj, Uint *recl);
-static int minor_collection(Process* p, int need, Eterm* objv, int nobj, Uint *recl);
-static void do_minor(Process *p, Uint new_sz, Eterm* objv, int nobj);
-static Eterm* sweep_rootset(Rootset *rootset, Eterm* htop, char* src, Uint src_size);
-static Eterm* sweep_one_area(Eterm* n_hp, Eterm* n_htop, char* src, Uint src_size);
-static Eterm* sweep_one_heap(Eterm* heap_ptr, Eterm* heap_end, Eterm* htop,
- char* src, Uint src_size);
-static Eterm* collect_heap_frags(Process* p, Eterm* heap,
- Eterm* htop, Eterm* objv, int nobj);
-static void adjust_after_fullsweep(Process *p, int need, Eterm *objv, int nobj);
+static Eterm *full_sweep_heaps(Process *p,
+ int hibernate,
+ Eterm *n_heap, Eterm* n_htop,
+ char *oh, Uint oh_size,
+ Eterm *objv, int nobj);
+static int garbage_collect(Process* p, ErlHeapFragment *live_hf_end,
+ int need, Eterm* objv, int nobj);
+static int major_collection(Process* p, ErlHeapFragment *live_hf_end,
+ int need, Eterm* objv, int nobj, Uint *recl);
+static int minor_collection(Process* p, ErlHeapFragment *live_hf_end,
+ int need, Eterm* objv, int nobj, Uint *recl);
+static void do_minor(Process *p, ErlHeapFragment *live_hf_end,
+ char *mature, Uint mature_size,
+ Uint new_sz, Eterm* objv, int nobj);
+static Eterm *sweep_new_heap(Eterm *n_hp, Eterm *n_htop,
+ char* old_heap, Uint old_heap_size);
+static Eterm *sweep_heaps(Eterm *n_hp, Eterm *n_htop,
+ char* old_heap, Uint old_heap_size);
+static Eterm* sweep_literal_area(Eterm* n_hp, Eterm* n_htop,
+ char* old_heap, Uint old_heap_size,
+ char* src, Uint src_size);
+static Eterm* sweep_literals_to_old_heap(Eterm* heap_ptr, Eterm* heap_end, Eterm* htop,
+ char* src, Uint src_size);
+static Eterm* collect_live_heap_frags(Process* p, ErlHeapFragment *live_hf_end,
+ Eterm* heap, Eterm* htop, Eterm* objv, int nobj);
+static int adjust_after_fullsweep(Process *p, int need, Eterm *objv, int nobj);
static void shrink_new_heap(Process *p, Uint new_sz, Eterm *objv, int nobj);
static void grow_new_heap(Process *p, Uint new_sz, Eterm* objv, int nobj);
static void sweep_off_heap(Process *p, int fullsweep);
@@ -119,13 +145,13 @@ static void offset_rootset(Process *p, Sint offs, char* area, Uint area_size,
Eterm* objv, int nobj);
static void offset_off_heap(Process* p, Sint offs, char* area, Uint area_size);
static void offset_mqueue(Process *p, Sint offs, char* area, Uint area_size);
+static void move_msgq_to_heap(Process *p);
static void init_gc_info(ErtsGCInfo *gcip);
#ifdef HARDDEBUG
static void disallow_heap_frag_ref_in_heap(Process* p);
static void disallow_heap_frag_ref_in_old_heap(Process* p);
-static void disallow_heap_frag_ref(Process* p, Eterm* n_htop, Eterm* objv, int nobj);
#endif
#if defined(ARCH_64)
@@ -147,6 +173,20 @@ typedef struct {
erts_smp_atomic32_t refc;
} ErtsGCInfoReq;
+static ERTS_INLINE int
+gc_cost(Uint gc_moved_live_words, Uint resize_moved_words)
+{
+ Sint reds;
+
+ reds = gc_moved_live_words/10;
+ reds += resize_moved_words/100;
+ if (reds < 1)
+ return 1;
+ if (reds > INT_MAX)
+ return INT_MAX;
+ return (int) reds;
+}
+
ERTS_SCHED_PREF_QUICK_ALLOC_IMPL(gcireq,
ErtsGCInfoReq,
5,
@@ -332,10 +372,19 @@ erts_offset_off_heap(ErlOffHeap *ohp, Sint offs, Eterm* low, Eterm* high)
#undef ptr_within
Eterm
-erts_gc_after_bif_call(Process* p, Eterm result, Eterm* regs, Uint arity)
+erts_gc_after_bif_call_lhf(Process* p, ErlHeapFragment *live_hf_end,
+ Eterm result, Eterm* regs, Uint arity)
{
int cost;
+ if (p->flags & F_HIBERNATE_SCHED) {
+ /*
+ * We just hibernated. We do *not* want to mess
+ * up the hibernation by an ordinary GC...
+ */
+ return result;
+ }
+
if (is_non_value(result)) {
if (p->freason == TRAP) {
#if HIPE
@@ -343,21 +392,28 @@ erts_gc_after_bif_call(Process* p, Eterm result, Eterm* regs, Uint arity)
regs = ERTS_PROC_GET_SCHDATA(p)->x_reg_array;
}
#endif
- cost = erts_garbage_collect(p, 0, regs, p->arity);
+ cost = garbage_collect(p, live_hf_end, 0, regs, p->arity);
} else {
- cost = erts_garbage_collect(p, 0, regs, arity);
+ cost = garbage_collect(p, live_hf_end, 0, regs, arity);
}
} else {
Eterm val[1];
val[0] = result;
- cost = erts_garbage_collect(p, 0, val, 1);
+ cost = garbage_collect(p, live_hf_end, 0, val, 1);
result = val[0];
}
BUMP_REDS(p, cost);
return result;
}
+Eterm
+erts_gc_after_bif_call(Process* p, Eterm result, Eterm* regs, Uint arity)
+{
+ return erts_gc_after_bif_call_lhf(p, ERTS_INVALID_HFRAG_PTR,
+ result, regs, arity);
+}
+
static ERTS_INLINE void reset_active_writer(Process *p)
{
struct erl_off_heap_header* ptr;
@@ -371,6 +427,139 @@ static ERTS_INLINE void reset_active_writer(Process *p)
}
}
+#define ERTS_DELAY_GC_EXTRA_FREE 40
+#define ERTS_ABANDON_HEAP_COST 10
+
+static int
+delay_garbage_collection(Process *p, ErlHeapFragment *live_hf_end, int need)
+{
+ ErlHeapFragment *hfrag;
+ Eterm *orig_heap, *orig_hend, *orig_htop, *orig_stop;
+ Eterm *stop, *hend;
+ Uint hsz, ssz;
+ int reds_left;
+
+ ERTS_HOLE_CHECK(p);
+
+ if ((p->flags & F_DISABLE_GC)
+ && p->live_hf_end == ERTS_INVALID_HFRAG_PTR) {
+ /*
+ * A BIF yielded with disabled GC. Remember
+ * heap fragments created by the BIF until we
+ * do next GC.
+ */
+ p->live_hf_end = live_hf_end;
+ }
+
+ if (need == 0)
+ return 1;
+
+ /*
+ * Satisfy need in a heap fragment...
+ */
+ ASSERT(need > 0);
+
+ orig_heap = p->heap;
+ orig_hend = p->hend;
+ orig_htop = p->htop;
+ orig_stop = p->stop;
+
+ ssz = orig_hend - orig_stop;
+ hsz = ssz + need + ERTS_DELAY_GC_EXTRA_FREE;
+
+ hfrag = new_message_buffer(hsz);
+ hfrag->next = p->mbuf;
+ p->mbuf = hfrag;
+ p->mbuf_sz += hsz;
+ p->heap = p->htop = &hfrag->mem[0];
+ p->hend = hend = &hfrag->mem[hsz];
+ p->stop = stop = hend - ssz;
+ sys_memcpy((void *) stop, (void *) orig_stop, ssz * sizeof(Eterm));
+
+ if (p->abandoned_heap) {
+ /* Active heap already in a fragment; adjust it... */
+ ErlHeapFragment *hfrag = ((ErlHeapFragment *)
+ (((char *) orig_heap)
+ - offsetof(ErlHeapFragment, mem)));
+ Uint unused = orig_hend - orig_htop;
+ ASSERT(hfrag->used_size == hfrag->alloc_size);
+ ASSERT(hfrag->used_size >= unused);
+ hfrag->used_size -= unused;
+ p->mbuf_sz -= unused;
+ }
+ else {
+ /* Do not leave a hole in the abandoned heap... */
+ if (orig_htop < orig_hend) {
+ *orig_htop = make_pos_bignum_header(orig_hend-orig_htop-1);
+ if (orig_htop + 1 < orig_hend) {
+ orig_hend[-1] = (Uint) (orig_htop - orig_heap);
+ p->flags |= F_ABANDONED_HEAP_USE;
+ }
+ }
+ p->abandoned_heap = orig_heap;
+ }
+
+#ifdef CHECK_FOR_HOLES
+ p->last_htop = p->htop;
+ p->heap_hfrag = hfrag;
+#endif
+
+ /* Make sure that we do a proper GC as soon as possible... */
+ p->flags |= F_FORCE_GC;
+ reds_left = ERTS_BIF_REDS_LEFT(p);
+ if (reds_left > ERTS_ABANDON_HEAP_COST) {
+ int vreds = reds_left - ERTS_ABANDON_HEAP_COST;
+ ERTS_VBUMP_REDS(p, vreds);
+ }
+ return ERTS_ABANDON_HEAP_COST;
+}
+
+static ERTS_FORCE_INLINE Uint
+young_gen_usage(Process *p)
+{
+ Uint hsz;
+ Eterm *aheap;
+
+ hsz = p->mbuf_sz;
+
+ if (p->flags & F_ON_HEAP_MSGQ) {
+ ErtsMessage *mp;
+ for (mp = p->msg.first; mp; mp = mp->next)
+ if (mp->data.attached)
+ hsz += erts_msg_attached_data_size(mp);
+ }
+
+ aheap = p->abandoned_heap;
+ if (!aheap)
+ hsz += p->htop - p->heap;
+ else {
+ /* used in orig heap */
+ if (p->flags & F_ABANDONED_HEAP_USE)
+ hsz += aheap[p->heap_sz-1];
+ else
+ hsz += p->heap_sz;
+ /* Remove unused part in latest fragment */
+ hsz -= p->hend - p->htop;
+ }
+ return hsz;
+}
+
+#define ERTS_GET_ORIG_HEAP(Proc, Heap, HTop) \
+ do { \
+ Eterm *aheap__ = (Proc)->abandoned_heap; \
+ if (!aheap__) { \
+ (Heap) = (Proc)->heap; \
+ (HTop) = (Proc)->htop; \
+ } \
+ else { \
+ (Heap) = aheap__; \
+ if ((Proc)->flags & F_ABANDONED_HEAP_USE) \
+ (HTop) = aheap__ + aheap__[(Proc)->heap_sz-1]; \
+ else \
+ (HTop) = aheap__ + (Proc)->heap_sz; \
+ } \
+ } while (0)
+
/*
* Garbage collect a process.
*
@@ -379,21 +568,25 @@ static ERTS_INLINE void reset_active_writer(Process *p)
* objv: Array of terms to add to rootset; that is to preserve.
* nobj: Number of objects in objv.
*/
-int
-erts_garbage_collect(Process* p, int need, Eterm* objv, int nobj)
+static int
+garbage_collect(Process* p, ErlHeapFragment *live_hf_end,
+ int need, Eterm* objv, int nobj)
{
Uint reclaimed_now = 0;
- int done = 0;
+ int reds;
ErtsMonotonicTime start_time = 0; /* Shut up faulty warning... */
ErtsSchedulerData *esdp;
#ifdef USE_VM_PROBES
DTRACE_CHARBUF(pidbuf, DTRACE_TERM_BUF_SIZE);
#endif
- if (p->flags & F_DISABLE_GC) {
- ASSERT(need == 0);
- return 1;
- }
+ if (p->flags & (F_DISABLE_GC|F_DELAY_GC))
+ return delay_garbage_collection(p, live_hf_end, need);
+
+ if (p->abandoned_heap)
+ live_hf_end = ERTS_INVALID_HFRAG_PTR;
+ else if (p->live_hf_end != ERTS_INVALID_HFRAG_PTR)
+ live_hf_end = p->live_hf_end;
esdp = erts_get_scheduler_data();
@@ -401,16 +594,14 @@ erts_garbage_collect(Process* p, int need, Eterm* objv, int nobj)
trace_gc(p, am_gc_start);
}
- (void) erts_smp_atomic32_read_bor_nob(&p->state, ERTS_PSFLG_GC);
+ erts_smp_atomic32_read_bor_nob(&p->state, ERTS_PSFLG_GC);
if (erts_system_monitor_long_gc != 0)
start_time = erts_get_monotonic_time(esdp);
ERTS_CHK_OFFHEAP(p);
ErtsGcQuickSanityCheck(p);
- if (GEN_GCS(p) >= MAX_GEN_GCS(p)) {
- FLAGS(p) |= F_NEED_FULLSWEEP;
- }
+
#ifdef USE_VM_PROBES
*pidbuf = '\0';
if (DTRACE_ENABLED(gc_major_start)
@@ -423,17 +614,21 @@ erts_garbage_collect(Process* p, int need, Eterm* objv, int nobj)
/*
* Test which type of GC to do.
*/
- while (!done) {
- if ((FLAGS(p) & F_NEED_FULLSWEEP) != 0) {
- DTRACE2(gc_major_start, pidbuf, need);
- done = major_collection(p, need, objv, nobj, &reclaimed_now);
- DTRACE2(gc_major_end, pidbuf, reclaimed_now);
- } else {
- DTRACE2(gc_minor_start, pidbuf, need);
- done = minor_collection(p, need, objv, nobj, &reclaimed_now);
- DTRACE2(gc_minor_end, pidbuf, reclaimed_now);
- }
+
+ if (GEN_GCS(p) < MAX_GEN_GCS(p) && !(FLAGS(p) & F_NEED_FULLSWEEP)) {
+ DTRACE2(gc_minor_start, pidbuf, need);
+ reds = minor_collection(p, live_hf_end, need, objv, nobj, &reclaimed_now);
+ DTRACE2(gc_minor_end, pidbuf, reclaimed_now);
+ if (reds < 0)
+ goto do_major_collection;
+ }
+ else {
+ do_major_collection:
+ DTRACE2(gc_major_start, pidbuf, need);
+ reds = major_collection(p, live_hf_end, need, objv, nobj, &reclaimed_now);
+ DTRACE2(gc_major_end, pidbuf, reclaimed_now);
}
+
reset_active_writer(p);
/*
@@ -472,6 +667,7 @@ erts_garbage_collect(Process* p, int need, Eterm* objv, int nobj)
esdp->gc_info.reclaimed += reclaimed_now;
FLAGS(p) &= ~F_FORCE_GC;
+ p->live_hf_end = ERTS_INVALID_HFRAG_PTR;
#ifdef CHECK_FOR_HOLES
/*
@@ -493,15 +689,20 @@ erts_garbage_collect(Process* p, int need, Eterm* objv, int nobj)
p->last_old_htop = p->old_htop;
#endif
- /* FIXME: This function should really return an Sint, i.e., a possibly
- 64 bit wide signed integer, but that requires updating all the code
- that calls it. For now, we just return INT_MAX if the result is too
- large for an int. */
- {
- Sint result = (HEAP_TOP(p) - HEAP_START(p)) / 10;
- if (result >= INT_MAX) return INT_MAX;
- else return (int) result;
- }
+ return reds;
+}
+
+int
+erts_garbage_collect_nobump(Process* p, int need, Eterm* objv, int nobj)
+{
+ return garbage_collect(p, ERTS_INVALID_HFRAG_PTR, need, objv, nobj);
+}
+
+void
+erts_garbage_collect(Process* p, int need, Eterm* objv, int nobj)
+{
+ int reds = garbage_collect(p, ERTS_INVALID_HFRAG_PTR, need, objv, nobj);
+ BUMP_REDS(p, reds);
}
/*
@@ -514,13 +715,11 @@ erts_garbage_collect_hibernate(Process* p)
Uint heap_size;
Eterm* heap;
Eterm* htop;
- Rootset rootset;
- char* src;
- Uint src_size;
Uint actual_size;
char* area;
Uint area_size;
Sint offs;
+ int reds;
if (p->flags & F_DISABLE_GC)
ERTS_INTERNAL_ERROR("GC disabled");
@@ -530,55 +729,34 @@ erts_garbage_collect_hibernate(Process* p)
*/
erts_smp_atomic32_read_bor_nob(&p->state, ERTS_PSFLG_GC);
ErtsGcQuickSanityCheck(p);
- ASSERT(p->mbuf_sz == 0);
- ASSERT(p->mbuf == 0);
+ ASSERT(p->mbuf == NULL);
ASSERT(p->stop == p->hend); /* Stack must be empty. */
+ ASSERT(!p->abandoned_heap);
/*
* Do it.
*/
- heap_size = p->heap_sz + (p->old_htop - p->old_heap);
+ heap_size = p->heap_sz + (p->old_htop - p->old_heap) + p->mbuf_sz;
heap = (Eterm*) ERTS_HEAP_ALLOC(ERTS_ALC_T_TMP_HEAP,
sizeof(Eterm)*heap_size);
htop = heap;
- (void) setup_rootset(p, p->arg_reg, p->arity, &rootset);
-#if HIPE
- hipe_empty_nstack(p);
-#endif
-
- src = (char *) p->heap;
- src_size = (char *) p->htop - src;
- htop = sweep_rootset(&rootset, htop, src, src_size);
- htop = sweep_one_area(heap, htop, src, src_size);
+ htop = full_sweep_heaps(p,
+ 1,
+ heap,
+ htop,
+ (char *) p->old_heap,
+ (char *) p->old_htop - (char *) p->old_heap,
+ p->arg_reg,
+ p->arity);
- if (p->old_heap) {
- src = (char *) p->old_heap;
- src_size = (char *) p->old_htop - src;
- htop = sweep_rootset(&rootset, htop, src, src_size);
- htop = sweep_one_area(heap, htop, src, src_size);
- }
-
- cleanup_rootset(&rootset);
-
- if (MSO(p).first) {
- sweep_off_heap(p, 1);
- }
-
- /*
- * Update all pointers.
- */
ERTS_HEAP_FREE(ERTS_ALC_T_HEAP,
- (void*)HEAP_START(p),
- HEAP_SIZE(p) * sizeof(Eterm));
- if (p->old_heap) {
- ERTS_HEAP_FREE(ERTS_ALC_T_OLD_HEAP,
- (void*)p->old_heap,
- (p->old_hend - p->old_heap) * sizeof(Eterm));
- p->old_heap = p->old_htop = p->old_hend = 0;
- }
+ (p->abandoned_heap
+ ? p->abandoned_heap
+ : p->heap),
+ p->heap_sz * sizeof(Eterm));
p->heap = heap;
p->high_water = htop;
@@ -593,6 +771,7 @@ erts_garbage_collect_hibernate(Process* p)
}
FLAGS(p) &= ~F_FORCE_GC;
+ p->live_hf_end = ERTS_INVALID_HFRAG_PTR;
/*
* Move the heap to its final destination.
@@ -612,6 +791,8 @@ erts_garbage_collect_hibernate(Process* p)
sys_memcpy((void *) heap, (void *) p->heap, actual_size*sizeof(Eterm));
ERTS_HEAP_FREE(ERTS_ALC_T_TMP_HEAP, p->heap, p->heap_sz*sizeof(Eterm));
+ remove_message_buffers(p);
+
p->stop = p->hend = heap + heap_size;
offs = heap - p->heap;
@@ -640,15 +821,18 @@ erts_garbage_collect_hibernate(Process* p)
ErtsGcQuickSanityCheck(p);
erts_smp_atomic32_read_band_nob(&p->state, ~ERTS_PSFLG_GC);
+
+ reds = gc_cost(actual_size, actual_size);
+ BUMP_REDS(p, reds);
}
void
erts_garbage_collect_literals(Process* p, Eterm* literals,
- Uint lit_size,
+ Uint byte_lit_size,
struct erl_off_heap_header* oh)
{
- Uint byte_lit_size = sizeof(Eterm)*lit_size;
+ Uint lit_size = byte_lit_size / sizeof(Eterm);
Uint old_heap_size;
Eterm* temp_lit;
Sint offs;
@@ -724,7 +908,7 @@ erts_garbage_collect_literals(Process* p, Eterm* literals,
if (IS_MOVED_BOXED(val)) {
ASSERT(is_boxed(val));
*g_ptr++ = val;
- } else if (in_area(ptr, area, area_size)) {
+ } else if (ErtsInArea(ptr, area, area_size)) {
MOVE_BOXED(ptr,val,old_htop,g_ptr++);
} else {
g_ptr++;
@@ -735,7 +919,7 @@ erts_garbage_collect_literals(Process* p, Eterm* literals,
val = *ptr;
if (IS_MOVED_CONS(val)) { /* Moved */
*g_ptr++ = ptr[1];
- } else if (in_area(ptr, area, area_size)) {
+ } else if (ErtsInArea(ptr, area, area_size)) {
MOVE_CONS(ptr,val,old_htop,g_ptr++);
} else {
g_ptr++;
@@ -755,8 +939,10 @@ erts_garbage_collect_literals(Process* p, Eterm* literals,
* Now we'll have to go through all heaps updating all other references.
*/
- old_htop = sweep_one_heap(p->heap, p->htop, old_htop, area, area_size);
- old_htop = sweep_one_area(p->old_heap, old_htop, area, area_size);
+ old_htop = sweep_literals_to_old_heap(p->heap, p->htop, old_htop, area, area_size);
+ old_htop = sweep_literal_area(p->old_heap, old_htop,
+ (char *) p->old_heap, sizeof(Eterm)*old_heap_size,
+ area, area_size);
ASSERT(p->old_htop <= old_htop && old_htop <= p->old_hend);
p->old_htop = old_htop;
@@ -815,15 +1001,18 @@ erts_garbage_collect_literals(Process* p, Eterm* literals,
}
static int
-minor_collection(Process* p, int need, Eterm* objv, int nobj, Uint *recl)
+minor_collection(Process* p, ErlHeapFragment *live_hf_end,
+ int need, Eterm* objv, int nobj, Uint *recl)
{
- Uint mature = HIGH_WATER(p) - HEAP_START(p);
+ Eterm *mature = p->abandoned_heap ? p->abandoned_heap : p->heap;
+ Uint mature_size = p->high_water - mature;
+ Uint size_before = young_gen_usage(p);
/*
* Allocate an old heap if we don't have one and if we'll need one.
*/
- if (OLD_HEAP(p) == NULL && mature != 0) {
+ if (OLD_HEAP(p) == NULL && mature_size != 0) {
Eterm* n_old;
/* Note: We choose a larger heap size than strictly needed,
@@ -831,7 +1020,7 @@ minor_collection(Process* p, int need, Eterm* objv, int nobj, Uint *recl)
* This improved Estone by more than 1200 estones on my computer
* (Ultra Sparc 10).
*/
- Uint new_sz = erts_next_heap_size(HEAP_TOP(p) - HEAP_START(p), 1);
+ Uint new_sz = erts_next_heap_size(size_before, 1);
/* Create new, empty old_heap */
n_old = (Eterm *) ERTS_HEAP_ALLOC(ERTS_ALC_T_OLD_HEAP,
@@ -847,40 +1036,32 @@ minor_collection(Process* p, int need, Eterm* objv, int nobj, Uint *recl)
*/
if (OLD_HEAP(p) &&
- ((mature <= OLD_HEND(p) - OLD_HTOP(p)) &&
- ((BIN_OLD_VHEAP_SZ(p) > BIN_OLD_VHEAP(p))) ) ) {
- ErlMessage *msgp;
- Uint size_after;
- Uint need_after;
- const Uint stack_size = STACK_SZ_ON_HEAP(p);
- const Uint size_before = MBUF_SIZE(p) + (HEAP_TOP(p) - HEAP_START(p));
- Uint new_sz = HEAP_SIZE(p) + MBUF_SIZE(p) + combined_message_size(p);
+ ((mature_size <= OLD_HEND(p) - OLD_HTOP(p)) &&
+ ((BIN_OLD_VHEAP_SZ(p) > BIN_OLD_VHEAP(p))) ) ) {
+ Eterm *prev_old_htop;
+ Uint stack_size, size_after, adjust_size, need_after, new_sz, new_mature;
+
+ stack_size = p->hend - p->stop;
+ new_sz = stack_size + size_before;
new_sz = next_heap_size(p, new_sz, 0);
- do_minor(p, new_sz, objv, nobj);
+ prev_old_htop = p->old_htop;
+ do_minor(p, live_hf_end, (char *) mature, mature_size*sizeof(Eterm),
+ new_sz, objv, nobj);
+
+ if (p->flags & F_ON_HEAP_MSGQ)
+ move_msgq_to_heap(p);
+
+ new_mature = p->old_htop - prev_old_htop;
- size_after = HEAP_TOP(p) - HEAP_START(p);
+ size_after = new_mature;
+ size_after += HEAP_TOP(p) - HEAP_START(p) + p->mbuf_sz;
*recl += (size_before - size_after);
- /*
- * Copy newly received message onto the end of the new heap.
- */
- ErtsGcQuickSanityCheck(p);
- for (msgp = p->msg.first; msgp; msgp = msgp->next) {
- if (msgp->data.attached) {
- ErtsHeapFactory factory;
- erts_factory_proc_prealloc_init(&factory, p,
- erts_msg_attached_data_size(msgp));
- erts_move_msg_attached_data_to_heap(&factory, msgp);
- erts_factory_close(&factory);
- ErtsGcQuickSanityCheck(p);
- }
- }
ErtsGcQuickSanityCheck(p);
GEN_GCS(p)++;
need_after = ((HEAP_TOP(p) - HEAP_START(p))
- + erts_used_frag_sz(MBUF(p))
+ need
+ stack_size);
@@ -893,6 +1074,8 @@ minor_collection(Process* p, int need, Eterm* objv, int nobj, Uint *recl)
* the heap size is substantial, we don't want to shrink.
*/
+ adjust_size = 0;
+
if ((HEAP_SIZE(p) > 3000) && (4 * need_after < HEAP_SIZE(p)) &&
((HEAP_SIZE(p) > 8000) ||
(HEAP_SIZE(p) > (OLD_HEND(p) - OLD_HEAP(p))))) {
@@ -914,28 +1097,33 @@ minor_collection(Process* p, int need, Eterm* objv, int nobj, Uint *recl)
: next_heap_size(p, wanted, 0);
if (wanted < HEAP_SIZE(p)) {
shrink_new_heap(p, wanted, objv, nobj);
+ adjust_size = p->htop - p->heap;
}
- ASSERT(HEAP_SIZE(p) == next_heap_size(p, HEAP_SIZE(p), 0));
- ASSERT(MBUF(p) == NULL);
- return 1; /* We are done. */
+ goto done;
}
if (HEAP_SIZE(p) >= need_after) {
/*
* The heap size turned out to be just right. We are done.
*/
- ASSERT(HEAP_SIZE(p) == next_heap_size(p, HEAP_SIZE(p), 0));
- ASSERT(MBUF(p) == NULL);
- return 1;
+ goto done;
}
+
+ grow_new_heap(p, next_heap_size(p, need_after, 0), objv, nobj);
+ adjust_size = p->htop - p->heap;
+
+ done:
+ ASSERT(HEAP_SIZE(p) == next_heap_size(p, HEAP_SIZE(p), 0));
+ ASSERT(MBUF(p) == NULL);
+
+ return gc_cost(size_after, adjust_size);
}
/*
- * Still not enough room after minor collection. Must force a major collection.
+ * Not enough room for a minor collection. Must force a major collection.
*/
- FLAGS(p) |= F_NEED_FULLSWEEP;
- return 0;
+ return -1;
}
/*
@@ -989,7 +1177,9 @@ static ERTS_INLINE void offset_nstack(Process* p, Sint offs,
#endif /* HIPE */
static void
-do_minor(Process *p, Uint new_sz, Eterm* objv, int nobj)
+do_minor(Process *p, ErlHeapFragment *live_hf_end,
+ char *mature, Uint mature_size,
+ Uint new_sz, Eterm* objv, int nobj)
{
Rootset rootset; /* Rootset for GC (stack, dictionary, etc). */
Roots* roots;
@@ -998,17 +1188,24 @@ do_minor(Process *p, Uint new_sz, Eterm* objv, int nobj)
Eterm* ptr;
Eterm val;
Eterm gval;
- char* heap = (char *) HEAP_START(p);
- Uint heap_size = (char *) HEAP_TOP(p) - heap;
- Uint mature_size = (char *) HIGH_WATER(p) - heap;
Eterm* old_htop = OLD_HTOP(p);
Eterm* n_heap;
+ char* oh = (char *) OLD_HEAP(p);
+ Uint oh_size = (char *) OLD_HTOP(p) - oh;
+
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] MINOR GC: %p %p %p %p\n", p->common.id,
+ HEAP_START(p), HEAP_END(p), OLD_HEAP(p), OLD_HEND(p)));
n_htop = n_heap = (Eterm*) ERTS_HEAP_ALLOC(ERTS_ALC_T_HEAP,
sizeof(Eterm)*new_sz);
- if (MBUF(p) != NULL) {
- n_htop = collect_heap_frags(p, n_heap, n_htop, objv, nobj);
+ if (live_hf_end != ERTS_INVALID_HFRAG_PTR) {
+ /*
+ * Move heap frags that we know are completely live
+ * directly into the new young heap generation.
+ */
+ n_htop = collect_live_heap_frags(p, live_hf_end, n_heap, n_htop,
+ objv, nobj);
}
n = setup_rootset(p, objv, nobj, &rootset);
@@ -1031,9 +1228,9 @@ do_minor(Process *p, Uint new_sz, Eterm* objv, int nobj)
if (IS_MOVED_BOXED(val)) {
ASSERT(is_boxed(val));
*g_ptr++ = val;
- } else if (in_area(ptr, heap, mature_size)) {
+ } else if (ErtsInArea(ptr, mature, mature_size)) {
MOVE_BOXED(ptr,val,old_htop,g_ptr++);
- } else if (in_area(ptr, heap, heap_size)) {
+ } else if (ErtsInYoungGen(gval, ptr, oh, oh_size)) {
MOVE_BOXED(ptr,val,n_htop,g_ptr++);
} else {
g_ptr++;
@@ -1046,9 +1243,9 @@ do_minor(Process *p, Uint new_sz, Eterm* objv, int nobj)
val = *ptr;
if (IS_MOVED_CONS(val)) { /* Moved */
*g_ptr++ = ptr[1];
- } else if (in_area(ptr, heap, mature_size)) {
+ } else if (ErtsInArea(ptr, mature, mature_size)) {
MOVE_CONS(ptr,val,old_htop,g_ptr++);
- } else if (in_area(ptr, heap, heap_size)) {
+ } else if (ErtsInYoungGen(gval, ptr, oh, oh_size)) {
MOVE_CONS(ptr,val,n_htop,g_ptr++);
} else {
g_ptr++;
@@ -1073,7 +1270,7 @@ do_minor(Process *p, Uint new_sz, Eterm* objv, int nobj)
*/
if (mature_size == 0) {
- n_htop = sweep_one_area(n_heap, n_htop, heap, heap_size);
+ n_htop = sweep_new_heap(n_heap, n_htop, oh, oh_size);
} else {
Eterm* n_hp = n_heap;
Eterm* ptr;
@@ -1090,9 +1287,9 @@ do_minor(Process *p, Uint new_sz, Eterm* objv, int nobj)
if (IS_MOVED_BOXED(val)) {
ASSERT(is_boxed(val));
*n_hp++ = val;
- } else if (in_area(ptr, heap, mature_size)) {
+ } else if (ErtsInArea(ptr, mature, mature_size)) {
MOVE_BOXED(ptr,val,old_htop,n_hp++);
- } else if (in_area(ptr, heap, heap_size)) {
+ } else if (ErtsInYoungGen(gval, ptr, oh, oh_size)) {
MOVE_BOXED(ptr,val,n_htop,n_hp++);
} else {
n_hp++;
@@ -1104,9 +1301,9 @@ do_minor(Process *p, Uint new_sz, Eterm* objv, int nobj)
val = *ptr;
if (IS_MOVED_CONS(val)) {
*n_hp++ = ptr[1];
- } else if (in_area(ptr, heap, mature_size)) {
+ } else if (ErtsInArea(ptr, mature, mature_size)) {
MOVE_CONS(ptr,val,old_htop,n_hp++);
- } else if (in_area(ptr, heap, heap_size)) {
+ } else if (ErtsInYoungGen(gval, ptr, oh, oh_size)) {
MOVE_CONS(ptr,val,n_htop,n_hp++);
} else {
n_hp++;
@@ -1126,10 +1323,10 @@ do_minor(Process *p, Uint new_sz, Eterm* objv, int nobj)
if (IS_MOVED_BOXED(val)) {
*origptr = val;
mb->base = binary_bytes(val);
- } else if (in_area(ptr, heap, mature_size)) {
+ } else if (ErtsInArea(ptr, mature, mature_size)) {
MOVE_BOXED(ptr,val,old_htop,origptr);
mb->base = binary_bytes(mb->orig);
- } else if (in_area(ptr, heap, heap_size)) {
+ } else if (ErtsInYoungGen(*origptr, ptr, oh, oh_size)) {
MOVE_BOXED(ptr,val,n_htop,origptr);
mb->base = binary_bytes(mb->orig);
}
@@ -1150,9 +1347,8 @@ do_minor(Process *p, Uint new_sz, Eterm* objv, int nobj)
* may point to the old (soon to be deleted) new_heap.
*/
- if (OLD_HTOP(p) < old_htop) {
- old_htop = sweep_one_area(OLD_HTOP(p), old_htop, heap, heap_size);
- }
+ if (OLD_HTOP(p) < old_htop)
+ old_htop = sweep_new_heap(OLD_HTOP(p), old_htop, oh, oh_size);
OLD_HTOP(p) = old_htop;
HIGH_WATER(p) = n_htop;
@@ -1184,8 +1380,12 @@ do_minor(Process *p, Uint new_sz, Eterm* objv, int nobj)
#endif
ERTS_HEAP_FREE(ERTS_ALC_T_HEAP,
- (void*)HEAP_START(p),
+ (p->abandoned_heap
+ ? p->abandoned_heap
+ : HEAP_START(p)),
HEAP_SIZE(p) * sizeof(Eterm));
+ p->abandoned_heap = NULL;
+ p->flags &= ~F_ABANDONED_HEAP_USE;
HEAP_START(p) = n_heap;
HEAP_TOP(p) = n_htop;
HEAP_SIZE(p) = new_sz;
@@ -1202,30 +1402,30 @@ do_minor(Process *p, Uint new_sz, Eterm* objv, int nobj)
*/
static int
-major_collection(Process* p, int need, Eterm* objv, int nobj, Uint *recl)
+major_collection(Process* p, ErlHeapFragment *live_hf_end,
+ int need, Eterm* objv, int nobj, Uint *recl)
{
- Rootset rootset;
- Roots* roots;
- const Uint size_before = ((HEAP_TOP(p) - HEAP_START(p))
- + (OLD_HTOP(p) - OLD_HEAP(p))
- + MBUF_SIZE(p));
+ Uint size_before, size_after, stack_size;
Eterm* n_heap;
Eterm* n_htop;
- char* src = (char *) HEAP_START(p);
- Uint src_size = (char *) HEAP_TOP(p) - src;
char* oh = (char *) OLD_HEAP(p);
Uint oh_size = (char *) OLD_HTOP(p) - oh;
- Uint n;
- Uint new_sz;
+ Uint new_sz, stk_sz;
+ int adjusted;
+
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] MAJOR GC: %p %p %p %p\n", p->common.id,
+ HEAP_START(p), HEAP_END(p), OLD_HEAP(p), OLD_HEND(p)));
/*
* Do a fullsweep GC. First figure out the size of the heap
* to receive all live data.
*/
- new_sz = (HEAP_SIZE(p) + MBUF_SIZE(p)
- + combined_message_size(p)
- + (OLD_HTOP(p) - OLD_HEAP(p)));
+ size_before = young_gen_usage(p);
+ size_before += p->old_htop - p->old_heap;
+ stack_size = p->hend - p->stop;
+
+ new_sz = stack_size + size_before;
new_sz = next_heap_size(p, new_sz, 0);
/*
@@ -1239,13 +1439,76 @@ major_collection(Process* p, int need, Eterm* objv, int nobj, Uint *recl)
n_htop = n_heap = (Eterm *) ERTS_HEAP_ALLOC(ERTS_ALC_T_HEAP,
sizeof(Eterm)*new_sz);
- /*
- * Get rid of heap fragments.
- */
+ if (live_hf_end != ERTS_INVALID_HFRAG_PTR) {
+ /*
+ * Move heap frags that we know are completely live
+ * directly into the heap.
+ */
+ n_htop = collect_live_heap_frags(p, live_hf_end, n_heap, n_htop,
+ objv, nobj);
+ }
- if (MBUF(p) != NULL) {
- n_htop = collect_heap_frags(p, n_heap, n_htop, objv, nobj);
+ n_htop = full_sweep_heaps(p, 0, n_heap, n_htop, oh, oh_size, objv, nobj);
+
+ /* Move the stack to the end of the heap */
+ stk_sz = HEAP_END(p) - p->stop;
+ sys_memcpy(n_heap + new_sz - stk_sz, p->stop, stk_sz * sizeof(Eterm));
+ p->stop = n_heap + new_sz - stk_sz;
+
+#ifdef USE_VM_PROBES
+ if (HEAP_SIZE(p) != new_sz && DTRACE_ENABLED(process_heap_grow)) {
+ DTRACE_CHARBUF(pidbuf, DTRACE_TERM_BUF_SIZE);
+
+ dtrace_proc_str(p, pidbuf);
+ DTRACE3(process_heap_grow, pidbuf, HEAP_SIZE(p), new_sz);
}
+#endif
+
+ ERTS_HEAP_FREE(ERTS_ALC_T_HEAP,
+ (p->abandoned_heap
+ ? p->abandoned_heap
+ : HEAP_START(p)),
+ p->heap_sz * sizeof(Eterm));
+ p->abandoned_heap = NULL;
+ p->flags &= ~F_ABANDONED_HEAP_USE;
+ HEAP_START(p) = n_heap;
+ HEAP_TOP(p) = n_htop;
+ HEAP_SIZE(p) = new_sz;
+ HEAP_END(p) = n_heap + new_sz;
+ GEN_GCS(p) = 0;
+
+ HIGH_WATER(p) = HEAP_TOP(p);
+
+ remove_message_buffers(p);
+
+ if (p->flags & F_ON_HEAP_MSGQ)
+ move_msgq_to_heap(p);
+
+ ErtsGcQuickSanityCheck(p);
+
+ size_after = HEAP_TOP(p) - HEAP_START(p) + p->mbuf_sz;
+ *recl += size_before - size_after;
+
+ adjusted = adjust_after_fullsweep(p, need, objv, nobj);
+
+#ifdef HARDDEBUG
+ disallow_heap_frag_ref_in_heap(p);
+#endif
+ ErtsGcQuickSanityCheck(p);
+
+ return gc_cost(size_after, adjusted ? size_after : 0);
+}
+
+static Eterm *
+full_sweep_heaps(Process *p,
+ int hibernate,
+ Eterm *n_heap, Eterm* n_htop,
+ char *oh, Uint oh_size,
+ Eterm *objv, int nobj)
+{
+ Rootset rootset;
+ Roots *roots;
+ Uint n;
/*
* Copy all top-level terms directly referenced by the rootset to
@@ -1253,7 +1516,14 @@ major_collection(Process* p, int need, Eterm* objv, int nobj, Uint *recl)
*/
n = setup_rootset(p, objv, nobj, &rootset);
- n_htop = fullsweep_nstack(p, n_htop);
+
+#ifdef HIPE
+ if (hibernate)
+ hipe_empty_nstack(p);
+ else
+ n_htop = fullsweep_nstack(p, n_htop);
+#endif
+
roots = rootset.roots;
while (n--) {
Eterm* g_ptr = roots->v;
@@ -1273,7 +1543,7 @@ major_collection(Process* p, int need, Eterm* objv, int nobj, Uint *recl)
if (IS_MOVED_BOXED(val)) {
ASSERT(is_boxed(val));
*g_ptr++ = val;
- } else if (in_area(ptr, src, src_size) || in_area(ptr, oh, oh_size)) {
+ } else if (!erts_is_literal(gval, ptr)) {
MOVE_BOXED(ptr,val,n_htop,g_ptr++);
} else {
g_ptr++;
@@ -1286,7 +1556,7 @@ major_collection(Process* p, int need, Eterm* objv, int nobj, Uint *recl)
val = *ptr;
if (IS_MOVED_CONS(val)) {
*g_ptr++ = ptr[1];
- } else if (in_area(ptr, src, src_size) || in_area(ptr, oh, oh_size)) {
+ } else if (!erts_is_literal(gval, ptr)) {
MOVE_CONS(ptr,val,n_htop,g_ptr++);
} else {
g_ptr++;
@@ -1311,74 +1581,7 @@ major_collection(Process* p, int need, Eterm* objv, int nobj, Uint *recl)
* until all is copied.
*/
- if (oh_size == 0) {
- n_htop = sweep_one_area(n_heap, n_htop, src, src_size);
- } else {
- Eterm* n_hp = n_heap;
-
- while (n_hp != n_htop) {
- Eterm* ptr;
- Eterm val;
- Eterm gval = *n_hp;
-
- switch (primary_tag(gval)) {
- case TAG_PRIMARY_BOXED: {
- ptr = boxed_val(gval);
- val = *ptr;
- if (IS_MOVED_BOXED(val)) {
- ASSERT(is_boxed(val));
- *n_hp++ = val;
- } else if (in_area(ptr, src, src_size) || in_area(ptr, oh, oh_size)) {
- MOVE_BOXED(ptr,val,n_htop,n_hp++);
- } else {
- n_hp++;
- }
- break;
- }
- case TAG_PRIMARY_LIST: {
- ptr = list_val(gval);
- val = *ptr;
- if (IS_MOVED_CONS(val)) {
- *n_hp++ = ptr[1];
- } else if (in_area(ptr, src, src_size) || in_area(ptr, oh, oh_size)) {
- MOVE_CONS(ptr,val,n_htop,n_hp++);
- } else {
- n_hp++;
- }
- break;
- }
- case TAG_PRIMARY_HEADER: {
- if (!header_is_thing(gval))
- n_hp++;
- else {
- if (header_is_bin_matchstate(gval)) {
- ErlBinMatchState *ms = (ErlBinMatchState*) n_hp;
- ErlBinMatchBuffer *mb = &(ms->mb);
- Eterm* origptr;
- origptr = &(mb->orig);
- ptr = boxed_val(*origptr);
- val = *ptr;
- if (IS_MOVED_BOXED(val)) {
- *origptr = val;
- mb->base = binary_bytes(*origptr);
- } else if (in_area(ptr, src, src_size) ||
- in_area(ptr, oh, oh_size)) {
- MOVE_BOXED(ptr,val,n_htop,origptr);
- mb->base = binary_bytes(*origptr);
- ptr = boxed_val(*origptr);
- val = *ptr;
- }
- }
- n_hp += (thing_arityval(gval)+1);
- }
- break;
- }
- default:
- n_hp++;
- break;
- }
- }
- }
+ n_htop = sweep_heaps(n_heap, n_htop, oh, oh_size);
if (MSO(p).first) {
sweep_off_heap(p, 1);
@@ -1391,67 +1594,13 @@ major_collection(Process* p, int need, Eterm* objv, int nobj, Uint *recl)
OLD_HEAP(p) = OLD_HTOP(p) = OLD_HEND(p) = NULL;
}
- /* Move the stack to the end of the heap */
- n = HEAP_END(p) - p->stop;
- sys_memcpy(n_heap + new_sz - n, p->stop, n * sizeof(Eterm));
- p->stop = n_heap + new_sz - n;
-
-#ifdef USE_VM_PROBES
- if (HEAP_SIZE(p) != new_sz && DTRACE_ENABLED(process_heap_grow)) {
- DTRACE_CHARBUF(pidbuf, DTRACE_TERM_BUF_SIZE);
-
- dtrace_proc_str(p, pidbuf);
- DTRACE3(process_heap_grow, pidbuf, HEAP_SIZE(p), new_sz);
- }
-#endif
-
- ERTS_HEAP_FREE(ERTS_ALC_T_HEAP,
- (void *) HEAP_START(p),
- (HEAP_END(p) - HEAP_START(p)) * sizeof(Eterm));
- HEAP_START(p) = n_heap;
- HEAP_TOP(p) = n_htop;
- HEAP_SIZE(p) = new_sz;
- HEAP_END(p) = n_heap + new_sz;
- GEN_GCS(p) = 0;
-
- HIGH_WATER(p) = HEAP_TOP(p);
-
- ErtsGcQuickSanityCheck(p);
-
- *recl += size_before - (HEAP_TOP(p) - HEAP_START(p));
-
- {
- ErlMessage *msgp;
-
- /*
- * Copy newly received message onto the end of the new heap.
- */
- for (msgp = p->msg.first; msgp; msgp = msgp->next) {
- if (msgp->data.attached) {
- ErtsHeapFactory factory;
- erts_factory_proc_prealloc_init(&factory, p,
- erts_msg_attached_data_size(msgp));
- erts_move_msg_attached_data_to_heap(&factory, msgp);
- erts_factory_close(&factory);
- ErtsGcQuickSanityCheck(p);
- }
- }
- }
-
- adjust_after_fullsweep(p, need, objv, nobj);
-
-#ifdef HARDDEBUG
- disallow_heap_frag_ref_in_heap(p);
-#endif
- remove_message_buffers(p);
-
- ErtsGcQuickSanityCheck(p);
- return 1; /* We are done. */
+ return n_htop;
}
-static void
+static int
adjust_after_fullsweep(Process *p, int need, Eterm *objv, int nobj)
{
+ int adjusted = 0;
Uint wanted, sz, need_after;
Uint stack_size = STACK_SZ_ON_HEAP(p);
@@ -1464,6 +1613,7 @@ adjust_after_fullsweep(Process *p, int need, Eterm *objv, int nobj)
/* Too small - grow to match requested need */
sz = next_heap_size(p, need_after, 0);
grow_new_heap(p, sz, objv, nobj);
+ adjusted = 1;
} else if (3 * HEAP_SIZE(p) < 4 * need_after){
/* Need more than 75% of current, postpone to next GC.*/
FLAGS(p) |= F_HEAP_GROW;
@@ -1480,25 +1630,10 @@ adjust_after_fullsweep(Process *p, int need, Eterm *objv, int nobj)
if (sz < HEAP_SIZE(p)) {
shrink_new_heap(p, sz, objv, nobj);
+ adjusted = 1;
}
}
-}
-
-/*
- * Return the size of all message buffers that are NOT linked in the
- * mbuf list.
- */
-static Uint
-combined_message_size(Process* p)
-{
- Uint sz;
- ErlMessage *msgp;
-
- for (sz = 0, msgp = p->msg.first; msgp; msgp = msgp->next) {
- if (msgp->data.attached)
- sz += erts_msg_attached_data_size(msgp);
- }
- return sz;
+ return adjusted;
}
/*
@@ -1511,6 +1646,10 @@ remove_message_buffers(Process* p)
free_message_buffer(MBUF(p));
MBUF(p) = NULL;
}
+ if (p->msg_frag) {
+ erts_cleanup_messages(p->msg_frag);
+ p->msg_frag = NULL;
+ }
MBUF_SIZE(p) = 0;
}
#ifdef HARDDEBUG
@@ -1522,64 +1661,6 @@ remove_message_buffers(Process* p)
* For performance reasons, we use _unchecked_list_val(), _unchecked_boxed_val(),
* and so on to avoid a function call.
*/
-
-static void
-disallow_heap_frag_ref(Process* p, Eterm* n_htop, Eterm* objv, int nobj)
-{
- ErlHeapFragment* mbuf;
- ErlHeapFragment* qb;
- Eterm gval;
- Eterm* ptr;
- Eterm val;
-
- ASSERT(p->htop != NULL);
- mbuf = MBUF(p);
-
- while (nobj--) {
- gval = *objv;
-
- switch (primary_tag(gval)) {
-
- case TAG_PRIMARY_BOXED: {
- ptr = _unchecked_boxed_val(gval);
- val = *ptr;
- if (IS_MOVED_BOXED(val)) {
- ASSERT(is_boxed(val));
- objv++;
- } else {
- for (qb = mbuf; qb != NULL; qb = qb->next) {
- if (in_area(ptr, qb->mem, qb->alloc_size*sizeof(Eterm))) {
- abort();
- }
- }
- objv++;
- }
- break;
- }
-
- case TAG_PRIMARY_LIST: {
- ptr = _unchecked_list_val(gval);
- val = *ptr;
- if (IS_MOVED_CONS(val)) {
- objv++;
- } else {
- for (qb = mbuf; qb != NULL; qb = qb->next) {
- if (in_area(ptr, qb->mem, qb->alloc_size*sizeof(Eterm))) {
- abort();
- }
- }
- objv++;
- }
- break;
- }
-
- default: {
- objv++;
- break;
- }
- }
- }
-}
static void
disallow_heap_frag_ref_in_heap(Process* p)
@@ -1607,9 +1688,9 @@ disallow_heap_frag_ref_in_heap(Process* p)
switch (primary_tag(val)) {
case TAG_PRIMARY_BOXED:
ptr = _unchecked_boxed_val(val);
- if (!in_area(ptr, heap, heap_size)) {
+ if (!ErtsInArea(ptr, heap, heap_size)) {
for (qb = MBUF(p); qb != NULL; qb = qb->next) {
- if (in_area(ptr, qb->mem, qb->alloc_size*sizeof(Eterm))) {
+ if (ErtsInArea(ptr, qb->mem, qb->alloc_size*sizeof(Eterm))) {
abort();
}
}
@@ -1617,9 +1698,9 @@ disallow_heap_frag_ref_in_heap(Process* p)
break;
case TAG_PRIMARY_LIST:
ptr = _unchecked_list_val(val);
- if (!in_area(ptr, heap, heap_size)) {
+ if (!ErtsInArea(ptr, heap, heap_size)) {
for (qb = MBUF(p); qb != NULL; qb = qb->next) {
- if (in_area(ptr, qb->mem, qb->alloc_size*sizeof(Eterm))) {
+ if (ErtsInArea(ptr, qb->mem, qb->alloc_size*sizeof(Eterm))) {
abort();
}
}
@@ -1662,12 +1743,12 @@ disallow_heap_frag_ref_in_old_heap(Process* p)
switch (primary_tag(val)) {
case TAG_PRIMARY_BOXED:
ptr = (Eterm *) val;
- if (!in_area(ptr, old_heap, old_heap_size)) {
- if (in_area(ptr, new_heap, new_heap_size)) {
+ if (!ErtsInArea(ptr, old_heap, old_heap_size)) {
+ if (ErtsInArea(ptr, new_heap, new_heap_size)) {
abort();
}
for (qb = MBUF(p); qb != NULL; qb = qb->next) {
- if (in_area(ptr, qb->mem, qb->alloc_size*sizeof(Eterm))) {
+ if (ErtsInArea(ptr, qb->mem, qb->alloc_size*sizeof(Eterm))) {
abort();
}
}
@@ -1675,12 +1756,12 @@ disallow_heap_frag_ref_in_old_heap(Process* p)
break;
case TAG_PRIMARY_LIST:
ptr = (Eterm *) val;
- if (!in_area(ptr, old_heap, old_heap_size)) {
- if (in_area(ptr, new_heap, new_heap_size)) {
+ if (!ErtsInArea(ptr, old_heap, old_heap_size)) {
+ if (ErtsInArea(ptr, new_heap, new_heap_size)) {
abort();
}
for (qb = MBUF(p); qb != NULL; qb = qb->next) {
- if (in_area(ptr, qb->mem, qb->alloc_size*sizeof(Eterm))) {
+ if (ErtsInArea(ptr, qb->mem, qb->alloc_size*sizeof(Eterm))) {
abort();
}
}
@@ -1689,7 +1770,7 @@ disallow_heap_frag_ref_in_old_heap(Process* p)
case TAG_PRIMARY_HEADER:
if (header_is_thing(val)) {
hp += _unchecked_thing_arityval(val);
- if (!in_area(hp, old_heap, old_heap_size+1)) {
+ if (!ErtsInArea(hp, old_heap, old_heap_size+1)) {
abort();
}
}
@@ -1699,66 +1780,30 @@ disallow_heap_frag_ref_in_old_heap(Process* p)
}
#endif
-static Eterm*
-sweep_rootset(Rootset* rootset, Eterm* htop, char* src, Uint src_size)
+typedef enum {
+ ErtsSweepNewHeap,
+ ErtsSweepHeaps,
+ ErtsSweepLiteralArea
+} ErtsSweepType;
+
+static ERTS_FORCE_INLINE Eterm *
+sweep(Eterm *n_hp, Eterm *n_htop,
+ ErtsSweepType type,
+ char *oh, Uint ohsz,
+ char *src, Uint src_size)
{
- Roots* roots = rootset->roots;
- Uint n = rootset->num_roots;
Eterm* ptr;
- Eterm gval;
Eterm val;
+ Eterm gval;
- while (n--) {
- Eterm* g_ptr = roots->v;
- Uint g_sz = roots->sz;
-
- roots++;
- while (g_sz--) {
- gval = *g_ptr;
-
- switch (primary_tag(gval)) {
- case TAG_PRIMARY_BOXED: {
- ptr = boxed_val(gval);
- val = *ptr;
- if (IS_MOVED_BOXED(val)) {
- ASSERT(is_boxed(val));
- *g_ptr++ = val;
- } else if (in_area(ptr, src, src_size)) {
- MOVE_BOXED(ptr,val,htop,g_ptr++);
- } else {
- g_ptr++;
- }
- break;
- }
- case TAG_PRIMARY_LIST: {
- ptr = list_val(gval);
- val = *ptr;
- if (IS_MOVED_CONS(val)) {
- *g_ptr++ = ptr[1];
- } else if (in_area(ptr, src, src_size)) {
- MOVE_CONS(ptr,val,htop,g_ptr++);
- } else {
- g_ptr++;
- }
- break;
- }
-
- default:
- g_ptr++;
- break;
- }
- }
- }
- return htop;
-}
-
+#undef ERTS_IS_IN_SWEEP_AREA
-static Eterm*
-sweep_one_area(Eterm* n_hp, Eterm* n_htop, char* src, Uint src_size)
-{
- Eterm* ptr;
- Eterm val;
- Eterm gval;
+#define ERTS_IS_IN_SWEEP_AREA(TPtr, Ptr) \
+ (type == ErtsSweepHeaps \
+ ? !erts_is_literal((TPtr), (Ptr)) \
+ : (type == ErtsSweepNewHeap \
+ ? ErtsInYoungGen((TPtr), (Ptr), oh, ohsz) \
+ : ErtsInArea((Ptr), src, src_size)))
while (n_hp != n_htop) {
ASSERT(n_hp < n_htop);
@@ -1770,7 +1815,7 @@ sweep_one_area(Eterm* n_hp, Eterm* n_htop, char* src, Uint src_size)
if (IS_MOVED_BOXED(val)) {
ASSERT(is_boxed(val));
*n_hp++ = val;
- } else if (in_area(ptr, src, src_size)) {
+ } else if (ERTS_IS_IN_SWEEP_AREA(gval, ptr)) {
MOVE_BOXED(ptr,val,n_htop,n_hp++);
} else {
n_hp++;
@@ -1782,7 +1827,7 @@ sweep_one_area(Eterm* n_hp, Eterm* n_htop, char* src, Uint src_size)
val = *ptr;
if (IS_MOVED_CONS(val)) {
*n_hp++ = ptr[1];
- } else if (in_area(ptr, src, src_size)) {
+ } else if (ERTS_IS_IN_SWEEP_AREA(gval, ptr)) {
MOVE_CONS(ptr,val,n_htop,n_hp++);
} else {
n_hp++;
@@ -1803,7 +1848,7 @@ sweep_one_area(Eterm* n_hp, Eterm* n_htop, char* src, Uint src_size)
if (IS_MOVED_BOXED(val)) {
*origptr = val;
mb->base = binary_bytes(*origptr);
- } else if (in_area(ptr, src, src_size)) {
+ } else if (ERTS_IS_IN_SWEEP_AREA(*origptr, ptr)) {
MOVE_BOXED(ptr,val,n_htop,origptr);
mb->base = binary_bytes(*origptr);
}
@@ -1818,10 +1863,41 @@ sweep_one_area(Eterm* n_hp, Eterm* n_htop, char* src, Uint src_size)
}
}
return n_htop;
+#undef ERTS_IS_IN_SWEEP_AREA
+}
+
+static Eterm *
+sweep_new_heap(Eterm *n_hp, Eterm *n_htop, char* old_heap, Uint old_heap_size)
+{
+ return sweep(n_hp, n_htop,
+ ErtsSweepNewHeap,
+ old_heap, old_heap_size,
+ NULL, 0);
+}
+
+static Eterm *
+sweep_heaps(Eterm *n_hp, Eterm *n_htop, char* old_heap, Uint old_heap_size)
+{
+ return sweep(n_hp, n_htop,
+ ErtsSweepHeaps,
+ old_heap, old_heap_size,
+ NULL, 0);
+}
+
+static Eterm *
+sweep_literal_area(Eterm *n_hp, Eterm *n_htop,
+ char* old_heap, Uint old_heap_size,
+ char* src, Uint src_size)
+{
+ return sweep(n_hp, n_htop,
+ ErtsSweepLiteralArea,
+ old_heap, old_heap_size,
+ src, src_size);
}
static Eterm*
-sweep_one_heap(Eterm* heap_ptr, Eterm* heap_end, Eterm* htop, char* src, Uint src_size)
+sweep_literals_to_old_heap(Eterm* heap_ptr, Eterm* heap_end, Eterm* htop,
+ char* src, Uint src_size)
{
while (heap_ptr < heap_end) {
Eterm* ptr;
@@ -1835,7 +1911,7 @@ sweep_one_heap(Eterm* heap_ptr, Eterm* heap_end, Eterm* htop, char* src, Uint sr
if (IS_MOVED_BOXED(val)) {
ASSERT(is_boxed(val));
*heap_ptr++ = val;
- } else if (in_area(ptr, src, src_size)) {
+ } else if (ErtsInArea(ptr, src, src_size)) {
MOVE_BOXED(ptr,val,htop,heap_ptr++);
} else {
heap_ptr++;
@@ -1847,7 +1923,7 @@ sweep_one_heap(Eterm* heap_ptr, Eterm* heap_end, Eterm* htop, char* src, Uint sr
val = *ptr;
if (IS_MOVED_CONS(val)) {
*heap_ptr++ = ptr[1];
- } else if (in_area(ptr, src, src_size)) {
+ } else if (ErtsInArea(ptr, src, src_size)) {
MOVE_CONS(ptr,val,htop,heap_ptr++);
} else {
heap_ptr++;
@@ -1868,7 +1944,7 @@ sweep_one_heap(Eterm* heap_ptr, Eterm* heap_end, Eterm* htop, char* src, Uint sr
if (IS_MOVED_BOXED(val)) {
*origptr = val;
mb->base = binary_bytes(*origptr);
- } else if (in_area(ptr, src, src_size)) {
+ } else if (ErtsInArea(ptr, src, src_size)) {
MOVE_BOXED(ptr,val,htop,origptr);
mb->base = binary_bytes(*origptr);
}
@@ -1919,32 +1995,21 @@ move_one_area(Eterm* n_htop, char* src, Uint src_size)
*/
static Eterm*
-collect_heap_frags(Process* p, Eterm* n_hstart, Eterm* n_htop,
- Eterm* objv, int nobj)
+collect_live_heap_frags(Process* p, ErlHeapFragment *live_hf_end,
+ Eterm* n_hstart, Eterm* n_htop,
+ Eterm* objv, int nobj)
{
ErlHeapFragment* qb;
char* frag_begin;
Uint frag_size;
/*
- * We don't allow references to a heap fragments from the stack, heap,
- * or process dictionary.
- */
-#ifdef HARDDEBUG
- disallow_heap_frag_ref(p, n_htop, p->stop, STACK_START(p) - p->stop);
- if (p->dictionary != NULL) {
- disallow_heap_frag_ref(p, n_htop, p->dictionary->data, p->dictionary->used);
- }
- disallow_heap_frag_ref_in_heap(p);
-#endif
-
- /*
* Move the heap fragments to the new heap. Note that no GC is done on
* the heap fragments. Any garbage will thus be moved as well and survive
* until next GC.
*/
qb = MBUF(p);
- while (qb != NULL) {
+ while (qb != live_hf_end) {
ASSERT(!qb->off_heap.first); /* process fragments use the MSO(p) list */
frag_size = qb->used_size * sizeof(Eterm);
if (frag_size != 0) {
@@ -1956,12 +2021,177 @@ collect_heap_frags(Process* p, Eterm* n_hstart, Eterm* n_htop,
return n_htop;
}
+static ERTS_INLINE void
+copy_one_frag(Eterm** hpp, ErlOffHeap* off_heap,
+ ErlHeapFragment *bp, Eterm *refs, int nrefs)
+{
+ Uint sz;
+ int i;
+ Sint offs;
+ struct erl_off_heap_header* oh;
+ Eterm *fhp, *hp;
+
+ OH_OVERHEAD(off_heap, bp->off_heap.overhead);
+ sz = bp->used_size;
+
+ fhp = bp->mem;
+ hp = *hpp;
+ offs = hp - fhp;
+
+ oh = NULL;
+ while (sz--) {
+ Uint cpy_sz;
+ Eterm val = *fhp++;
+
+ switch (primary_tag(val)) {
+ case TAG_PRIMARY_IMMED1:
+ *hp++ = val;
+ break;
+ case TAG_PRIMARY_LIST:
+ case TAG_PRIMARY_BOXED:
+ *hp++ = offset_ptr(val, offs);
+ break;
+ case TAG_PRIMARY_HEADER:
+ *hp++ = val;
+ switch (val & _HEADER_SUBTAG_MASK) {
+ case ARITYVAL_SUBTAG:
+ break;
+ case REFC_BINARY_SUBTAG:
+ case FUN_SUBTAG:
+ case EXTERNAL_PID_SUBTAG:
+ case EXTERNAL_PORT_SUBTAG:
+ case EXTERNAL_REF_SUBTAG:
+ oh = (struct erl_off_heap_header*) (hp-1);
+ cpy_sz = thing_arityval(val);
+ goto cpy_words;
+ default:
+ cpy_sz = header_arity(val);
+
+ cpy_words:
+ ASSERT(sz >= cpy_sz);
+ sz -= cpy_sz;
+ while (cpy_sz >= 8) {
+ cpy_sz -= 8;
+ *hp++ = *fhp++;
+ *hp++ = *fhp++;
+ *hp++ = *fhp++;
+ *hp++ = *fhp++;
+ *hp++ = *fhp++;
+ *hp++ = *fhp++;
+ *hp++ = *fhp++;
+ *hp++ = *fhp++;
+ }
+ switch (cpy_sz) {
+ case 7: *hp++ = *fhp++;
+ case 6: *hp++ = *fhp++;
+ case 5: *hp++ = *fhp++;
+ case 4: *hp++ = *fhp++;
+ case 3: *hp++ = *fhp++;
+ case 2: *hp++ = *fhp++;
+ case 1: *hp++ = *fhp++;
+ default: break;
+ }
+ if (oh) {
+ /* Add to offheap list */
+ oh->next = off_heap->first;
+ off_heap->first = oh;
+ ASSERT(*hpp <= (Eterm*)oh);
+ ASSERT(hp > (Eterm*)oh);
+ oh = NULL;
+ }
+ break;
+ }
+ break;
+ }
+ }
+
+ ASSERT(bp->used_size == hp - *hpp);
+ *hpp = hp;
+
+ for (i = 0; i < nrefs; i++) {
+ if (is_not_immed(refs[i]))
+ refs[i] = offset_ptr(refs[i], offs);
+ }
+ bp->off_heap.first = NULL;
+}
+
+static void
+move_msgq_to_heap(Process *p)
+{
+ ErtsMessage **mpp = &p->msg.first;
+
+ while (*mpp) {
+ ErtsMessage *mp = *mpp;
+
+ if (mp->data.attached) {
+ ErlHeapFragment *bp;
+ ErtsHeapFactory factory;
+
+ erts_factory_proc_prealloc_init(&factory, p,
+ erts_msg_attached_data_size(mp));
+
+ if (is_non_value(ERL_MESSAGE_TERM(mp))) {
+ if (mp->data.dist_ext) {
+ ASSERT(mp->data.dist_ext->heap_size >= 0);
+ if (is_not_nil(ERL_MESSAGE_TOKEN(mp))) {
+ bp = erts_dist_ext_trailer(mp->data.dist_ext);
+ ERL_MESSAGE_TOKEN(mp) = copy_struct(ERL_MESSAGE_TOKEN(mp),
+ bp->used_size,
+ &factory.hp,
+ factory.off_heap);
+ erts_cleanup_offheap(&bp->off_heap);
+ }
+ ERL_MESSAGE_TERM(mp) = erts_decode_dist_ext(&factory,
+ mp->data.dist_ext);
+ erts_free_dist_ext_copy(mp->data.dist_ext);
+ mp->data.dist_ext = NULL;
+ }
+ }
+ else {
+
+ if (mp->data.attached == ERTS_MSG_COMBINED_HFRAG)
+ bp = &mp->hfrag;
+ else
+ bp = mp->data.heap_frag;
+
+ if (bp->next)
+ erts_move_multi_frags(&factory.hp, factory.off_heap, bp,
+ mp->m, ERL_MESSAGE_REF_ARRAY_SZ, 0);
+ else
+ copy_one_frag(&factory.hp, factory.off_heap, bp,
+ mp->m, ERL_MESSAGE_REF_ARRAY_SZ);
+
+ if (mp->data.attached != ERTS_MSG_COMBINED_HFRAG) {
+ mp->data.heap_frag = NULL;
+ free_message_buffer(bp);
+ }
+ else {
+ ErtsMessage *tmp = erts_alloc_message(0, NULL);
+ sys_memcpy((void *) tmp->m, (void *) mp->m,
+ sizeof(Eterm)*ERL_MESSAGE_REF_ARRAY_SZ);
+ tmp->next = mp->next;
+ if (p->msg.save == &mp->next)
+ p->msg.save = &tmp->next;
+ if (p->msg.last == &mp->next)
+ p->msg.last = &tmp->next;
+ *mpp = tmp;
+ mp->next = NULL;
+ erts_cleanup_messages(mp);
+ mp = tmp;
+ }
+ }
+
+ erts_factory_close(&factory);
+ }
+
+ mpp = &(*mpp)->next;
+ }
+}
+
static Uint
setup_rootset(Process *p, Eterm *objv, int nobj, Rootset *rootset)
{
- Uint avail;
Roots* roots;
- ErlMessage* mp;
Uint n;
n = 0;
@@ -1984,7 +2214,7 @@ setup_rootset(Process *p, Eterm *objv, int nobj, Rootset *rootset)
}
ASSERT((is_nil(p->seq_trace_token) ||
- is_tuple(follow_moved(p->seq_trace_token)) ||
+ is_tuple(follow_moved(p->seq_trace_token, (Eterm) 0)) ||
is_atom(p->seq_trace_token)));
if (is_not_immed(p->seq_trace_token)) {
roots[n].v = &p->seq_trace_token;
@@ -2002,7 +2232,7 @@ setup_rootset(Process *p, Eterm *objv, int nobj, Rootset *rootset)
is_internal_pid(ERTS_TRACER_PROC(p)) ||
is_internal_port(ERTS_TRACER_PROC(p)));
- ASSERT(is_pid(follow_moved(p->group_leader)));
+ ASSERT(is_pid(follow_moved(p->group_leader, (Eterm) 0)));
if (is_not_immed(p->group_leader)) {
roots[n].v = &p->group_leader;
roots[n].sz = 1;
@@ -2039,31 +2269,47 @@ setup_rootset(Process *p, Eterm *objv, int nobj, Rootset *rootset)
ASSERT(n <= rootset->size);
- mp = p->msg.first;
- avail = rootset->size - n;
- while (mp != NULL) {
- if (avail == 0) {
- Uint new_size = 2*rootset->size;
- if (roots == rootset->def) {
- roots = erts_alloc(ERTS_ALC_T_ROOTSET,
- new_size*sizeof(Roots));
- sys_memcpy(roots, rootset->def, sizeof(rootset->def));
- } else {
- roots = erts_realloc(ERTS_ALC_T_ROOTSET,
- (void *) roots,
- new_size*sizeof(Roots));
- }
+ switch (p->flags & (F_OFF_HEAP_MSGQ|F_OFF_HEAP_MSGQ_CHNG)) {
+ case F_OFF_HEAP_MSGQ|F_OFF_HEAP_MSGQ_CHNG:
+ (void) erts_move_messages_off_heap(p);
+ case F_OFF_HEAP_MSGQ:
+ break;
+ case F_OFF_HEAP_MSGQ_CHNG:
+ case 0: {
+ /*
+ * We do not have off heap message queue enabled, i.e. we
+ * need to add message queue to rootset...
+ */
+ ErtsMessage *mp;
+
+ /* Ensure large enough rootset... */
+ if (n + p->msg.len > rootset->size) {
+ Uint new_size = n + p->msg.len;
+ ERTS_GC_ASSERT(roots == rootset->def);
+ roots = erts_alloc(ERTS_ALC_T_ROOTSET,
+ new_size*sizeof(Roots));
+ sys_memcpy(roots, rootset->def, n*sizeof(Roots));
rootset->size = new_size;
- avail = new_size - n;
}
- if (mp->data.attached == NULL) {
- roots[n].v = mp->m;
- roots[n].sz = 2;
- n++;
- avail--;
+
+ for (mp = p->msg.first; mp; mp = mp->next) {
+
+ if (!mp->data.attached) {
+ /*
+ * Message may refer data on heap;
+ * add it to rootset...
+ */
+ roots[n].v = mp->m;
+ roots[n].sz = ERL_MESSAGE_REF_ARRAY_SZ;
+ n++;
+ }
}
- mp = mp->next;
+ break;
}
+ }
+
+ ASSERT(rootset->size >= n);
+
rootset->roots = roots;
rootset->num_roots = n;
return n;
@@ -2303,11 +2549,11 @@ sweep_off_heap(Process *p, int fullsweep)
*/
while (ptr) {
if (IS_MOVED_BOXED(ptr->thing_word)) {
- ASSERT(!in_area(ptr, oheap, oheap_sz));
+ ASSERT(!ErtsInArea(ptr, oheap, oheap_sz));
*prev = ptr = (struct erl_off_heap_header*) boxed_val(ptr->thing_word);
ASSERT(!IS_MOVED_BOXED(ptr->thing_word));
if (ptr->thing_word == HEADER_PROC_BIN) {
- int to_new_heap = !in_area(ptr, oheap, oheap_sz);
+ int to_new_heap = !ErtsInArea(ptr, oheap, oheap_sz);
ASSERT(to_new_heap == !seen_mature || (!to_new_heap && (seen_mature=1)));
if (to_new_heap) {
bin_vheap += ptr->size / sizeof(Eterm);
@@ -2321,7 +2567,7 @@ sweep_off_heap(Process *p, int fullsweep)
ptr = ptr->next;
}
}
- else if (!in_area(ptr, oheap, oheap_sz)) {
+ else if (!ErtsInArea(ptr, oheap, oheap_sz)) {
/* garbage */
switch (thing_subtag(ptr->thing_word)) {
case REFC_BINARY_SUBTAG:
@@ -2353,7 +2599,7 @@ sweep_off_heap(Process *p, int fullsweep)
* generational collection - keep objects in list.
*/
while (ptr) {
- ASSERT(in_area(ptr, oheap, oheap_sz));
+ ASSERT(ErtsInArea(ptr, oheap, oheap_sz));
ASSERT(!IS_MOVED_BOXED(ptr->thing_word));
if (ptr->thing_word == HEADER_PROC_BIN) {
BIN_OLD_VHEAP(p) += ptr->size / sizeof(Eterm); /* for binary gc (words)*/
@@ -2442,7 +2688,7 @@ offset_heap(Eterm* hp, Uint sz, Sint offs, char* area, Uint area_size)
switch (primary_tag(val)) {
case TAG_PRIMARY_LIST:
case TAG_PRIMARY_BOXED:
- if (in_area(ptr_val(val), area, area_size)) {
+ if (ErtsInArea(ptr_val(val), area, area_size)) {
*hp = offset_ptr(val, offs);
}
hp++;
@@ -2464,7 +2710,7 @@ offset_heap(Eterm* hp, Uint sz, Sint offs, char* area, Uint area_size)
{
struct erl_off_heap_header* oh = (struct erl_off_heap_header*) hp;
- if (in_area(oh->next, area, area_size)) {
+ if (ErtsInArea(oh->next, area, area_size)) {
Eterm** uptr = (Eterm **) (void *) &oh->next;
*uptr += offs; /* Patch the mso chain */
}
@@ -2474,7 +2720,7 @@ offset_heap(Eterm* hp, Uint sz, Sint offs, char* area, Uint area_size)
{
ErlBinMatchState *ms = (ErlBinMatchState*) hp;
ErlBinMatchBuffer *mb = &(ms->mb);
- if (in_area(ptr_val(mb->orig), area, area_size)) {
+ if (ErtsInArea(ptr_val(mb->orig), area, area_size)) {
mb->orig = offset_ptr(mb->orig, offs);
mb->base = binary_bytes(mb->orig);
}
@@ -2504,7 +2750,7 @@ offset_heap_ptr(Eterm* hp, Uint sz, Sint offs, char* area, Uint area_size)
switch (primary_tag(val)) {
case TAG_PRIMARY_LIST:
case TAG_PRIMARY_BOXED:
- if (in_area(ptr_val(val), area, area_size)) {
+ if (ErtsInArea(ptr_val(val), area, area_size)) {
*hp = offset_ptr(val, offs);
}
hp++;
@@ -2519,7 +2765,7 @@ offset_heap_ptr(Eterm* hp, Uint sz, Sint offs, char* area, Uint area_size)
static void
offset_off_heap(Process* p, Sint offs, char* area, Uint area_size)
{
- if (MSO(p).first && in_area((Eterm *)MSO(p).first, area, area_size)) {
+ if (MSO(p).first && ErtsInArea((Eterm *)MSO(p).first, area, area_size)) {
Eterm** uptr = (Eterm**) (void *) &MSO(p).first;
*uptr += offs;
}
@@ -2531,7 +2777,7 @@ offset_off_heap(Process* p, Sint offs, char* area, Uint area_size)
static void
offset_mqueue(Process *p, Sint offs, char* area, Uint area_size)
{
- ErlMessage* mp = p->msg.first;
+ ErtsMessage* mp = p->msg.first;
while (mp != NULL) {
Eterm mesg = ERL_MESSAGE_TERM(mp);
@@ -2539,19 +2785,19 @@ offset_mqueue(Process *p, Sint offs, char* area, Uint area_size)
switch (primary_tag(mesg)) {
case TAG_PRIMARY_LIST:
case TAG_PRIMARY_BOXED:
- if (in_area(ptr_val(mesg), area, area_size)) {
+ if (ErtsInArea(ptr_val(mesg), area, area_size)) {
ERL_MESSAGE_TERM(mp) = offset_ptr(mesg, offs);
}
break;
}
}
mesg = ERL_MESSAGE_TOKEN(mp);
- if (is_boxed(mesg) && in_area(ptr_val(mesg), area, area_size)) {
+ if (is_boxed(mesg) && ErtsInArea(ptr_val(mesg), area, area_size)) {
ERL_MESSAGE_TOKEN(mp) = offset_ptr(mesg, offs);
}
#ifdef USE_VM_PROBES
mesg = ERL_MESSAGE_DT_UTAG(mp);
- if (is_boxed(mesg) && in_area(ptr_val(mesg), area, area_size)) {
+ if (is_boxed(mesg) && ErtsInArea(ptr_val(mesg), area, area_size)) {
ERL_MESSAGE_DT_UTAG(mp) = offset_ptr(mesg, offs);
}
#endif
@@ -2618,7 +2864,7 @@ reply_gc_info(void *vgcirp)
Eterm **hpp;
Uint sz, *szp;
ErlOffHeap *ohp = NULL;
- ErlHeapFragment *bp = NULL;
+ ErtsMessage *mp = NULL;
ASSERT(esdp);
@@ -2644,12 +2890,13 @@ reply_gc_info(void *vgcirp)
if (hpp)
break;
- hp = erts_alloc_message_heap(sz, &bp, &ohp, rp, &rp_locks);
+ mp = erts_alloc_message_heap(rp, &rp_locks, sz, &hp, &ohp);
+
szp = NULL;
hpp = &hp;
}
- erts_queue_message(rp, &rp_locks, bp, msg, NIL);
+ erts_queue_message(rp, &rp_locks, mp, msg, NIL);
if (gcirp->req_sched == esdp->no)
rp_locks &= ~ERTS_PROC_LOCK_MAIN;
@@ -2701,36 +2948,49 @@ erts_gc_info_request(Process *c_p)
static int
within2(Eterm *ptr, Process *p, Eterm *real_htop)
{
- ErlHeapFragment* bp = MBUF(p);
- ErlMessage* mp = p->msg.first;
- Eterm *htop = real_htop ? real_htop : HEAP_TOP(p);
+ ErlHeapFragment* bp;
+ ErtsMessage* mp;
+ Eterm *htop, *heap;
+
+ if (p->abandoned_heap)
+ ERTS_GET_ORIG_HEAP(p, heap, htop);
+ else {
+ heap = p->heap;
+ htop = real_htop ? real_htop : HEAP_TOP(p);
+ }
if (OLD_HEAP(p) && (OLD_HEAP(p) <= ptr && ptr < OLD_HEND(p))) {
return 1;
}
- if (HEAP_START(p) <= ptr && ptr < htop) {
+ if (heap <= ptr && ptr < htop) {
return 1;
}
- while (bp != NULL) {
- if (bp->mem <= ptr && ptr < bp->mem + bp->used_size) {
- return 1;
- }
- bp = bp->next;
- }
+
+ mp = p->msg_frag;
+ bp = p->mbuf;
+
+ if (bp)
+ goto search_heap_frags;
+
while (mp) {
- if (mp->data.attached) {
- ErlHeapFragment *hfp;
- if (is_value(ERL_MESSAGE_TERM(mp)))
- hfp = mp->data.heap_frag;
- else if (is_not_nil(ERL_MESSAGE_TOKEN(mp)))
- hfp = erts_dist_ext_trailer(mp->data.dist_ext);
- else
- hfp = NULL;
- if (hfp && hfp->mem <= ptr && ptr < hfp->mem + hfp->used_size)
+
+ if (mp->data.attached == ERTS_MSG_COMBINED_HFRAG)
+ bp = &mp->hfrag;
+ else
+ bp = mp->data.heap_frag;
+
+ mp = mp->next;
+
+ search_heap_frags:
+
+ while (bp) {
+ if (bp->mem <= ptr && ptr < bp->mem + bp->used_size) {
return 1;
+ }
+ bp = bp->next;
}
- mp = mp->next;
}
+
return 0;
}
@@ -2752,11 +3012,11 @@ do { \
__FILE__, __LINE__, #EXP); \
} while (0)
+
#ifdef ERTS_OFFHEAP_DEBUG_CHK_CIRCULAR_LIST
# define ERTS_OFFHEAP_VISITED_BIT ((Eterm) 1 << 31)
#endif
-
void
erts_check_off_heap2(Process *p, Eterm *htop)
{
@@ -2785,7 +3045,7 @@ erts_check_off_heap2(Process *p, Eterm *htop)
}
ERTS_CHK_OFFHEAP_ASSERT(refc >= 1);
#ifdef ERTS_OFFHEAP_DEBUG_CHK_CIRCULAR_LIST
- ERTS_CHK_OFFHEAP_ASSERT(!(u.hdr->thing_word & ERTS_EXTERNAL_VISITED_BIT));
+ ERTS_CHK_OFFHEAP_ASSERT(!(u.hdr->thing_word & ERTS_OFFHEAP_VISITED_BIT));
u.hdr->thing_word |= ERTS_OFFHEAP_VISITED_BIT;
#endif
if (old) {
@@ -2798,7 +3058,7 @@ erts_check_off_heap2(Process *p, Eterm *htop)
}
}
-#ifdef ERTS_OFFHEAP_DEBUG_CHK_CIRCULAR_EXTERNAL_LIST
+#ifdef ERTS_OFFHEAP_DEBUG_CHK_CIRCULAR_LIST
for (u.hdr = MSO(p).first; u.hdr; u.hdr = u.hdr->next)
u.hdr->thing_word &= ~ERTS_OFFHEAP_VISITED_BIT;
#endif
diff --git a/erts/emulator/beam/erl_gc.h b/erts/emulator/beam/erl_gc.h
index ecd1bf4d22..d603866cbf 100644
--- a/erts/emulator/beam/erl_gc.h
+++ b/erts/emulator/beam/erl_gc.h
@@ -69,17 +69,18 @@ do { \
while (nelts--) *HTOP++ = *PTR++; \
} while(0)
-#define in_area(ptr,start,nbytes) \
- ((UWord)((char*)(ptr) - (char*)(start)) < (nbytes))
-
#if defined(DEBUG) || defined(ERTS_OFFHEAP_DEBUG)
int within(Eterm *ptr, Process *p);
#endif
-ERTS_GLB_INLINE Eterm follow_moved(Eterm term);
+#define ErtsInYoungGen(TPtr, Ptr, OldHeap, OldHeapSz) \
+ (!erts_is_literal((TPtr), (Ptr)) \
+ & !ErtsInArea((Ptr), (OldHeap), (OldHeapSz)))
+
+ERTS_GLB_INLINE Eterm follow_moved(Eterm term, Eterm xptr_tag);
#if ERTS_GLB_INLINE_INCL_FUNC_DEF
-ERTS_GLB_INLINE Eterm follow_moved(Eterm term)
+ERTS_GLB_INLINE Eterm follow_moved(Eterm term, Eterm xptr_tag)
{
Eterm* ptr;
switch (primary_tag(term)) {
@@ -87,17 +88,18 @@ ERTS_GLB_INLINE Eterm follow_moved(Eterm term)
break;
case TAG_PRIMARY_BOXED:
ptr = boxed_val(term);
- if (IS_MOVED_BOXED(*ptr)) term = *ptr;
+ if (IS_MOVED_BOXED(*ptr)) term = (*ptr) | xptr_tag;
break;
case TAG_PRIMARY_LIST:
ptr = list_val(term);
- if (IS_MOVED_CONS(ptr[0])) term = ptr[1];
+ if (IS_MOVED_CONS(ptr[0])) term = (ptr[1]) | xptr_tag;
break;
default:
ASSERT(!"strange tag in follow_moved");
}
return term;
}
+
#endif
#endif /* ERL_GC_C__ || HIPE_GC_C__ */
@@ -106,6 +108,23 @@ ERTS_GLB_INLINE Eterm follow_moved(Eterm term)
* Global exported
*/
+#define ERTS_IS_GC_DESIRED_INTERNAL(Proc, HTop, STop) \
+ ((((STop) - (HTop) < (Proc)->mbuf_sz)) \
+ | ((Proc)->off_heap.overhead > (Proc)->bin_vheap_sz) \
+ | !!((Proc)->flags & F_FORCE_GC))
+
+#define ERTS_IS_GC_DESIRED(Proc) \
+ ERTS_IS_GC_DESIRED_INTERNAL((Proc), (Proc)->htop, (Proc)->stop)
+
+#define ERTS_FORCE_GC_INTERNAL(Proc, FCalls) \
+ do { \
+ (Proc)->flags |= F_FORCE_GC; \
+ ERTS_VBUMP_ALL_REDS_INTERNAL((Proc), (FCalls)); \
+ } while (0)
+
+#define ERTS_FORCE_GC(Proc) \
+ ERTS_FORCE_GC_INTERNAL((Proc), (Proc)->fcalls)
+
extern Uint erts_test_long_gc_sleep;
typedef struct {
@@ -115,8 +134,11 @@ typedef struct {
void erts_gc_info(ErtsGCInfo *gcip);
void erts_init_gc(void);
-int erts_garbage_collect(struct process*, int, Eterm*, int);
+int erts_garbage_collect_nobump(struct process*, int, Eterm*, int);
+void erts_garbage_collect(struct process*, int, Eterm*, int);
void erts_garbage_collect_hibernate(struct process* p);
+Eterm erts_gc_after_bif_call_lhf(struct process* p, ErlHeapFragment *live_hf_end,
+ Eterm result, Eterm* regs, Uint arity);
Eterm erts_gc_after_bif_call(struct process* p, Eterm result, Eterm* regs, Uint arity);
void erts_garbage_collect_literals(struct process* p, Eterm* literals,
Uint lit_size,
diff --git a/erts/emulator/beam/erl_hl_timer.c b/erts/emulator/beam/erl_hl_timer.c
index 51a0d68247..6853278828 100644
--- a/erts/emulator/beam/erl_hl_timer.c
+++ b/erts/emulator/beam/erl_hl_timer.c
@@ -1245,7 +1245,9 @@ hlt_bif_timer_timeout(ErtsHLTimer *tmr, Uint32 roflgs)
* the middle of tree destruction).
*/
if (!ERTS_PROC_IS_EXITING(proc)) {
- erts_queue_message(proc, &proc_locks, tmr->btm.bp,
+ ErtsMessage *mp = erts_alloc_message(0, NULL);
+ mp->data.heap_frag = tmr->btm.bp;
+ erts_queue_message(proc, &proc_locks, mp,
tmr->btm.message, NIL);
erts_smp_proc_unlock(proc, ERTS_PROC_LOCKS_MSG_SEND);
queued_message = 1;
@@ -1926,36 +1928,31 @@ access_sched_local_btm(Process *c_p, Eterm pid,
if (proc) {
Uint hsz;
- ErlOffHeap *ohp;
- ErlHeapFragment* bp;
+ ErtsMessage *mp;
Eterm *hp, msg, ref, result;
+ ErlOffHeap *ohp;
+ Uint32 *refn;
#ifdef ERTS_HLT_DEBUG
Eterm *hp_end;
#endif
- hsz = 3; /* 2-tuple */
- if (!async)
- hsz += REF_THING_SIZE;
+ hsz = REF_THING_SIZE;
+ if (async) {
+ refn = trefn; /* timer ref */
+ hsz += 4; /* 3-tuple */
+ }
else {
- if (is_non_value(tref) || proc != c_p)
- hsz += REF_THING_SIZE;
- hsz += 1; /* upgrade to 3-tuple */
+ refn = rrefn; /* request ref */
+ hsz += 3; /* 2-tuple */
}
+
+ ERTS_HLT_ASSERT(refn);
+
if (time_left > (Sint64) MAX_SMALL)
hsz += ERTS_SINT64_HEAP_SIZE(time_left);
- if (proc == c_p) {
- bp = NULL;
- ohp = NULL;
- hp = HAlloc(c_p, hsz);
- }
- else {
- hp = erts_alloc_message_heap(hsz,
- &bp,
- &ohp,
- proc,
- &proc_locks);
- }
+ mp = erts_alloc_message_heap(proc, &proc_locks,
+ hsz, &hp, &ohp);
#ifdef ERTS_HLT_DEBUG
hp_end = hp + hsz;
@@ -1968,35 +1965,22 @@ access_sched_local_btm(Process *c_p, Eterm pid,
else
result = erts_sint64_to_big(time_left, &hp);
- if (!async) {
- write_ref_thing(hp,
- rrefn[0],
- rrefn[1],
- rrefn[2]);
- ref = make_internal_ref(hp);
- hp += REF_THING_SIZE;
- msg = TUPLE2(hp, ref, result);
+ write_ref_thing(hp,
+ refn[0],
+ refn[1],
+ refn[2]);
+ ref = make_internal_ref(hp);
+ hp += REF_THING_SIZE;
- ERTS_HLT_ASSERT(hp + 3 == hp_end);
- }
- else {
- Eterm tag = cancel ? am_cancel_timer : am_read_timer;
- if (is_value(tref) && proc == c_p)
- ref = tref;
- else {
- write_ref_thing(hp,
- trefn[0],
- trefn[1],
- trefn[2]);
- ref = make_internal_ref(hp);
- hp += REF_THING_SIZE;
- }
- msg = TUPLE3(hp, tag, ref, result);
+ msg = (async
+ ? TUPLE3(hp, (cancel
+ ? am_cancel_timer
+ : am_read_timer), ref, result)
+ : TUPLE2(hp, ref, result));
- ERTS_HLT_ASSERT(hp + 4 == hp_end);
+ ERTS_HLT_ASSERT(hp + (async ? 4 : 3) == hp_end);
- }
- erts_queue_message(proc, &proc_locks, bp, msg, NIL);
+ erts_queue_message(proc, &proc_locks, mp, msg, NIL);
if (c_p)
proc_locks &= ~ERTS_PROC_LOCK_MAIN;
@@ -2093,16 +2077,19 @@ try_access_sched_remote_btm(ErtsSchedulerData *esdp,
}
}
else {
+ ErtsMessage *mp;
Eterm tag, res, msg;
Uint hsz;
Eterm *hp;
ErtsProcLocks proc_locks = ERTS_PROC_LOCK_MAIN;
+ ErlOffHeap *ohp;
hsz = 4;
if (time_left > (Sint64) MAX_SMALL)
hsz += ERTS_SINT64_HEAP_SIZE(time_left);
- hp = HAlloc(c_p, hsz);
+ mp = erts_alloc_message_heap(c_p, &proc_locks,
+ hsz, &hp, &ohp);
if (cancel)
tag = am_cancel_timer;
else
@@ -2117,7 +2104,7 @@ try_access_sched_remote_btm(ErtsSchedulerData *esdp,
msg = TUPLE3(hp, tag, tref, res);
- erts_queue_message(c_p, &proc_locks, NULL, msg, NIL);
+ erts_queue_message(c_p, &proc_locks, mp, msg, NIL);
proc_locks &= ~ERTS_PROC_LOCK_MAIN;
if (proc_locks)
diff --git a/erts/emulator/beam/erl_init.c b/erts/emulator/beam/erl_init.c
index 69c0de81be..e3390c2769 100644
--- a/erts/emulator/beam/erl_init.c
+++ b/erts/emulator/beam/erl_init.c
@@ -432,7 +432,7 @@ erl_first_process_otp(char* modname, void* code, unsigned size, int argc, char**
hp += 2;
args = CONS(hp, env, args);
- so.flags = SPO_SYSTEM_PROC;
+ so.flags = erts_default_spo_flags|SPO_SYSTEM_PROC;
res = erl_create_process(&parent, start_mod, am_start, args, &so);
erts_smp_proc_unlock(&parent, ERTS_PROC_LOCK_MAIN);
erts_cleanup_empty_process(&parent);
@@ -631,6 +631,8 @@ void erts_usage(void)
erts_fprintf(stderr, "-W<i|w|e> set error logger warnings mapping,\n");
erts_fprintf(stderr, " see error_logger documentation for details\n");
+ erts_fprintf(stderr, "-xmqd val set default message queue data flag for processes,\n");
+ erts_fprintf(stderr, " valid values are: off_heap | on_heap | mixed\n");
erts_fprintf(stderr, "-zdbbl size set the distribution buffer busy limit in kilobytes\n");
erts_fprintf(stderr, " valid range is [1-%d]\n", INT_MAX/1024);
erts_fprintf(stderr, "-zdntgc time set delayed node table gc in seconds\n");
@@ -1401,6 +1403,7 @@ erl_start(int argc, char **argv)
case 't': verbose |= DEBUG_THREADS; break;
case 'p': verbose |= DEBUG_PROCESSES; break;
case 'm': verbose |= DEBUG_MESSAGES; break;
+ case 'c': verbose |= DEBUG_SHCOPY; break;
default : erts_fprintf(stderr,"Unknown verbose option: %c\n",*ch);
}
}
@@ -1413,6 +1416,7 @@ erl_start(int argc, char **argv)
if (verbose & DEBUG_THREADS) erts_printf("THREADS ");
if (verbose & DEBUG_PROCESSES) erts_printf("PROCESSES ");
if (verbose & DEBUG_MESSAGES) erts_printf("MESSAGES ");
+ if (verbose & DEBUG_SHCOPY) erts_printf("SHCOPY ");
erts_printf("\n");
#else
erts_fprintf(stderr, "warning: -v (only in debug compiled code)\n");
@@ -2016,6 +2020,32 @@ erl_start(int argc, char **argv)
}
break;
+ case 'x': {
+ char *sub_param = argv[i]+2;
+ if (has_prefix("mqd", sub_param)) {
+ arg = get_arg(sub_param+3, argv[i+1], &i);
+ if (sys_strcmp(arg, "mixed") == 0)
+ erts_default_spo_flags &= ~(SPO_ON_HEAP_MSGQ|SPO_OFF_HEAP_MSGQ);
+ else if (sys_strcmp(arg, "on_heap") == 0) {
+ erts_default_spo_flags &= ~SPO_OFF_HEAP_MSGQ;
+ erts_default_spo_flags |= SPO_ON_HEAP_MSGQ;
+ }
+ else if (sys_strcmp(arg, "off_heap") == 0) {
+ erts_default_spo_flags &= ~SPO_ON_HEAP_MSGQ;
+ erts_default_spo_flags |= SPO_OFF_HEAP_MSGQ;
+ }
+ else {
+ erts_fprintf(stderr,
+ "Invalid message_queue_data flag: %s\n", arg);
+ erts_usage();
+ }
+ } else {
+ erts_fprintf(stderr, "bad -x option %s\n", argv[i]);
+ erts_usage();
+ }
+ break;
+ }
+
case 'z': {
char *sub_param = argv[i]+2;
@@ -2069,7 +2099,8 @@ erl_start(int argc, char **argv)
"Invalid ets busy wait threshold: %s\n", arg);
erts_usage();
}
- } else {
+ }
+ else {
erts_fprintf(stderr, "bad -z option %s\n", argv[i]);
erts_usage();
}
diff --git a/erts/emulator/beam/erl_map.c b/erts/emulator/beam/erl_map.c
index 29b3024644..d0ffb11e79 100644
--- a/erts/emulator/beam/erl_map.c
+++ b/erts/emulator/beam/erl_map.c
@@ -2698,32 +2698,88 @@ BIF_RETTYPE erts_internal_map_to_tuple_keys_1(BIF_ALIST_1) {
}
/*
- * erts_internal:map_type/1
+ * erts_internal:term_type/1
*
* Used in erts_debug:size/1
*/
-BIF_RETTYPE erts_internal_map_type_1(BIF_ALIST_1) {
- DECL_AM(hashmap);
- DECL_AM(hashmap_node);
- DECL_AM(flatmap);
- if (is_map(BIF_ARG_1)) {
- Eterm hdr = *(boxed_val(BIF_ARG_1));
- ASSERT(is_header(hdr));
- switch (hdr & _HEADER_MAP_SUBTAG_MASK) {
- case HAMT_SUBTAG_HEAD_FLATMAP:
- BIF_RET(AM_flatmap);
- case HAMT_SUBTAG_HEAD_ARRAY:
- case HAMT_SUBTAG_HEAD_BITMAP:
- BIF_RET(AM_hashmap);
- case HAMT_SUBTAG_NODE_BITMAP:
- BIF_RET(AM_hashmap_node);
- default:
- erl_exit(1, "bad header");
+BIF_RETTYPE erts_internal_term_type_1(BIF_ALIST_1) {
+ Eterm obj = BIF_ARG_1;
+ switch (primary_tag(obj)) {
+ case TAG_PRIMARY_LIST:
+ BIF_RET(ERTS_MAKE_AM("list"));
+ case TAG_PRIMARY_BOXED: {
+ Eterm hdr = *boxed_val(obj);
+ ASSERT(is_header(hdr));
+ switch (hdr & _TAG_HEADER_MASK) {
+ case ARITYVAL_SUBTAG:
+ BIF_RET(ERTS_MAKE_AM("tuple"));
+ case EXPORT_SUBTAG:
+ BIF_RET(ERTS_MAKE_AM("export"));
+ case FUN_SUBTAG:
+ BIF_RET(ERTS_MAKE_AM("fun"));
+ case MAP_SUBTAG:
+ switch (MAP_HEADER_TYPE(hdr)) {
+ case MAP_HEADER_TAG_FLATMAP_HEAD :
+ BIF_RET(ERTS_MAKE_AM("flatmap"));
+ case MAP_HEADER_TAG_HAMT_HEAD_BITMAP :
+ case MAP_HEADER_TAG_HAMT_HEAD_ARRAY :
+ BIF_RET(ERTS_MAKE_AM("hashmap"));
+ case MAP_HEADER_TAG_HAMT_NODE_BITMAP :
+ BIF_RET(ERTS_MAKE_AM("hashmap_node"));
+ default:
+ erl_exit(ERTS_ABORT_EXIT, "term_type: bad map header type %d\n", MAP_HEADER_TYPE(hdr));
+ }
+ case REFC_BINARY_SUBTAG:
+ BIF_RET(ERTS_MAKE_AM("refc_binary"));
+ case HEAP_BINARY_SUBTAG:
+ BIF_RET(ERTS_MAKE_AM("heap_binary"));
+ case SUB_BINARY_SUBTAG:
+ BIF_RET(ERTS_MAKE_AM("sub_binary"));
+ case BIN_MATCHSTATE_SUBTAG:
+ BIF_RET(ERTS_MAKE_AM("matchstate"));
+ case POS_BIG_SUBTAG:
+ case NEG_BIG_SUBTAG:
+ BIF_RET(ERTS_MAKE_AM("bignum"));
+ case REF_SUBTAG:
+ BIF_RET(ERTS_MAKE_AM("reference"));
+ case EXTERNAL_REF_SUBTAG:
+ BIF_RET(ERTS_MAKE_AM("external_reference"));
+ case EXTERNAL_PID_SUBTAG:
+ BIF_RET(ERTS_MAKE_AM("external_pid"));
+ case EXTERNAL_PORT_SUBTAG:
+ BIF_RET(ERTS_MAKE_AM("external_port"));
+ case FLOAT_SUBTAG:
+ BIF_RET(ERTS_MAKE_AM("hfloat"));
+ default:
+ erl_exit(ERTS_ABORT_EXIT, "term_type: Invalid tag (0x%X)\n", hdr);
+ }
}
+ case TAG_PRIMARY_IMMED1:
+ switch (obj & _TAG_IMMED1_MASK) {
+ case _TAG_IMMED1_SMALL:
+ BIF_RET(ERTS_MAKE_AM("fixnum"));
+ case _TAG_IMMED1_PID:
+ BIF_RET(ERTS_MAKE_AM("pid"));
+ case _TAG_IMMED1_PORT:
+ BIF_RET(ERTS_MAKE_AM("port"));
+ case _TAG_IMMED1_IMMED2:
+ switch (obj & _TAG_IMMED2_MASK) {
+ case _TAG_IMMED2_ATOM:
+ BIF_RET(ERTS_MAKE_AM("atom"));
+ case _TAG_IMMED2_CATCH:
+ BIF_RET(ERTS_MAKE_AM("catch"));
+ case _TAG_IMMED2_NIL:
+ BIF_RET(ERTS_MAKE_AM("nil"));
+ default:
+ erl_exit(ERTS_ABORT_EXIT, "term_type: Invalid tag (0x%X)\n", obj);
+ }
+ default:
+ erl_exit(ERTS_ABORT_EXIT, "term_type: Invalid tag (0x%X)\n", obj);
+ }
+ default:
+ erl_exit(ERTS_ABORT_EXIT, "term_type: Invalid tag (0x%X)\n", obj);
}
- BIF_P->fvalue = BIF_ARG_1;
- BIF_ERROR(BIF_P, BADMAP);
}
/*
diff --git a/erts/emulator/beam/erl_map.h b/erts/emulator/beam/erl_map.h
index be6f791a4e..052fa99f03 100644
--- a/erts/emulator/beam/erl_map.h
+++ b/erts/emulator/beam/erl_map.h
@@ -180,14 +180,17 @@ typedef struct hashmap_head_s {
[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.
*/
-#define HASHMAP_HEAP_SIZE(KEYS,NODES) ((KEYS)*3 + (NODES)*2)
+#define HASHMAP_WORDS_PER_KEY 3
+#define HASHMAP_WORDS_PER_NODE 2
#ifdef DEBUG
-# define HASHMAP_ESTIMATED_NODE_COUNT(KEYS) (KEYS)
+# define HASHMAP_ESTIMATED_TOT_NODE_SIZE(KEYS) \
+ (HASHMAP_WORDS_PER_NODE * (KEYS) * 3/10) /* slightly under estimated */
#else
-# define HASHMAP_ESTIMATED_NODE_COUNT(KEYS) (2*(KEYS)/5)
+# define HASHMAP_ESTIMATED_TOT_NODE_SIZE(KEYS) \
+ (HASHMAP_WORDS_PER_NODE * (KEYS) * 4/10) /* slightly over estimated */
#endif
#define HASHMAP_ESTIMATED_HEAP_SIZE(KEYS) \
- HASHMAP_HEAP_SIZE(KEYS,HASHMAP_ESTIMATED_NODE_COUNT(KEYS))
-
+ ((KEYS)*HASHMAP_WORDS_PER_KEY + HASHMAP_ESTIMATED_TOT_NODE_SIZE(KEYS))
#endif
diff --git a/erts/emulator/beam/erl_message.c b/erts/emulator/beam/erl_message.c
index ef52823287..ac5ec79fe4 100644
--- a/erts/emulator/beam/erl_message.c
+++ b/erts/emulator/beam/erl_message.c
@@ -33,8 +33,8 @@
#include "erl_binary.h"
#include "dtrace-wrapper.h"
-ERTS_SCHED_PREF_QUICK_ALLOC_IMPL(message,
- ErlMessage,
+ERTS_SCHED_PREF_QUICK_ALLOC_IMPL(message_ref,
+ ErtsMessageRef,
ERL_MESSAGE_BUF_SZ,
ERTS_ALC_T_MSG_REF)
@@ -44,27 +44,20 @@ ERTS_SCHED_PREF_QUICK_ALLOC_IMPL(message,
#undef HARD_DEBUG
#endif
-
-
-
-#ifdef DEBUG
-static ERTS_INLINE int in_heapfrag(const Eterm* ptr, const ErlHeapFragment *bp)
+void
+init_message(void)
{
- return ((unsigned)(ptr - bp->mem) < bp->used_size);
+ init_message_ref_alloc();
}
-#endif
-
-void
-init_message(void)
+void *erts_alloc_message_ref(void)
{
- init_message_alloc();
+ return (void *) message_ref_alloc();
}
-void
-free_message(ErlMessage* mp)
+void erts_free_message_ref(void *mp)
{
- message_free(mp);
+ message_ref_free((ErtsMessageRef *) mp);
}
/* Allocate message buffer (size in words) */
@@ -74,7 +67,8 @@ new_message_buffer(Uint size)
ErlHeapFragment* bp;
bp = (ErlHeapFragment*) ERTS_HEAP_ALLOC(ERTS_ALC_T_HEAP_FRAG,
ERTS_HEAP_FRAG_SIZE(size));
- ERTS_INIT_HEAP_FRAG(bp, size);
+ ERTS_INIT_HEAP_FRAG(bp, size, size);
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] new message buffer %p\n", erts_get_current_pid(), bp->mem));
return bp;
}
@@ -203,83 +197,57 @@ free_message_buffer(ErlHeapFragment* bp)
}while (bp != NULL);
}
-static ERTS_INLINE void
-link_mbuf_to_proc(Process *proc, ErlHeapFragment *bp)
+void
+erts_cleanup_messages(ErtsMessage *msgp)
{
- if (bp) {
- /* Link the message buffer */
- bp->next = MBUF(proc);
- MBUF(proc) = bp;
- MBUF_SIZE(proc) += bp->used_size;
- FLAGS(proc) |= F_FORCE_GC;
-
- /* Move any off_heap's into the process */
- if (bp->off_heap.first != NULL) {
- struct erl_off_heap_header** next_p = &bp->off_heap.first;
- while (*next_p != NULL) {
- next_p = &((*next_p)->next);
+ ErtsMessage *mp = msgp;
+ while (mp) {
+ ErtsMessage *fmp;
+ ErlHeapFragment *bp;
+ if (is_non_value(ERL_MESSAGE_TERM(mp))) {
+ if (is_not_immed(ERL_MESSAGE_TOKEN(mp))) {
+ bp = (ErlHeapFragment *) mp->data.dist_ext->ext_endp;
+ erts_cleanup_offheap(&bp->off_heap);
+ }
+ if (mp->data.dist_ext)
+ erts_free_dist_ext_copy(mp->data.dist_ext);
+ }
+ else {
+ if (mp->data.attached != ERTS_MSG_COMBINED_HFRAG)
+ bp = mp->data.heap_frag;
+ else {
+ bp = mp->hfrag.next;
+ erts_cleanup_offheap(&mp->hfrag.off_heap);
}
- *next_p = MSO(proc).first;
- MSO(proc).first = bp->off_heap.first;
- bp->off_heap.first = NULL;
- OH_OVERHEAD(&(MSO(proc)), bp->off_heap.overhead);
+ if (bp)
+ free_message_buffer(bp);
}
+ fmp = mp;
+ mp = mp->next;
+ erts_free_message(fmp);
}
}
-Eterm
-erts_msg_distext2heap(Process *pp,
- ErtsProcLocks *plcksp,
- ErlHeapFragment **bpp,
- Eterm *tokenp,
- ErtsDistExternal *dist_extp)
+ErtsMessage *
+erts_realloc_shrink_message(ErtsMessage *mp, Uint sz, Eterm *brefs, Uint brefs_size)
{
- Eterm msg;
- Uint tok_sz = 0;
- Eterm *hp = NULL;
- ErtsHeapFactory factory;
- Sint sz;
-
- *bpp = NULL;
- sz = erts_decode_dist_ext_size(dist_extp);
- if (sz < 0)
- goto decode_error;
- if (is_not_nil(*tokenp)) {
- ErlHeapFragment *heap_frag = erts_dist_ext_trailer(dist_extp);
- tok_sz = heap_frag->used_size;
- sz += tok_sz;
- }
- if (pp) {
- ErlOffHeap *ohp;
- hp = erts_alloc_message_heap(sz, bpp, &ohp, pp, plcksp);
- }
- else {
- *bpp = new_message_buffer(sz);
- hp = (*bpp)->mem;
- }
- erts_factory_message_init(&factory, pp, hp, *bpp);
- msg = erts_decode_dist_ext(&factory, dist_extp);
- if (is_non_value(msg))
- goto decode_error;
- if (is_not_nil(*tokenp)) {
- ErlHeapFragment *heap_frag = erts_dist_ext_trailer(dist_extp);
- hp = erts_produce_heap(&factory, tok_sz, 0);
- *tokenp = copy_struct(*tokenp, tok_sz, &hp, factory.off_heap);
- erts_cleanup_offheap(&heap_frag->off_heap);
+ ErtsMessage *nmp = erts_realloc(ERTS_ALC_T_MSG, mp,
+ sizeof(ErtsMessage) + (sz - 1)*sizeof(Eterm));
+ if (nmp != mp) {
+ Eterm *sp = &mp->hfrag.mem[0];
+ Eterm *ep = sp + sz;
+ Sint offs = &nmp->hfrag.mem[0] - sp;
+ erts_offset_off_heap(&nmp->hfrag.off_heap, offs, sp, ep);
+ erts_offset_heap(&nmp->hfrag.mem[0], sz, offs, sp, ep);
+ if (brefs && brefs_size)
+ erts_offset_heap_ptr(brefs, brefs_size, offs, sp, ep);
}
- erts_free_dist_ext_copy(dist_extp);
- erts_factory_close(&factory);
- return msg;
- decode_error:
- if (is_not_nil(*tokenp)) {
- ErlHeapFragment *heap_frag = erts_dist_ext_trailer(dist_extp);
- erts_cleanup_offheap(&heap_frag->off_heap);
- }
- erts_free_dist_ext_copy(dist_extp);
- *bpp = NULL;
- return THE_NON_VALUE;
- }
+ nmp->hfrag.used_size = sz;
+ nmp->hfrag.alloc_size = sz;
+
+ return nmp;
+}
void
erts_queue_dist_message(Process *rcvr,
@@ -287,7 +255,7 @@ erts_queue_dist_message(Process *rcvr,
ErtsDistExternal *dist_ext,
Eterm token)
{
- ErlMessage* mp;
+ ErtsMessage* mp;
#ifdef USE_VM_PROBES
Sint tok_label = 0;
Sint tok_lastcnt = 0;
@@ -299,7 +267,17 @@ erts_queue_dist_message(Process *rcvr,
ERTS_SMP_LC_ASSERT(*rcvr_locks == erts_proc_lc_my_proc_locks(rcvr));
- mp = message_alloc();
+ mp = erts_alloc_message(0, NULL);
+ mp->data.dist_ext = dist_ext;
+
+ ERL_MESSAGE_TERM(mp) = THE_NON_VALUE;
+#ifdef USE_VM_PROBES
+ ERL_MESSAGE_DT_UTAG(mp) = NIL;
+ if (token == am_have_dt_utag)
+ ERL_MESSAGE_TOKEN(mp) = NIL;
+ else
+#endif
+ ERL_MESSAGE_TOKEN(mp) = token;
#ifdef ERTS_SMP
if (!(*rcvr_locks & ERTS_PROC_LOCK_MSGQ)) {
@@ -318,64 +296,46 @@ erts_queue_dist_message(Process *rcvr,
if (!(*rcvr_locks & ERTS_PROC_LOCK_MSGQ))
erts_smp_proc_unlock(rcvr, ERTS_PROC_LOCK_MSGQ);
/* Drop message if receiver is exiting or has a pending exit ... */
- if (is_not_nil(token)) {
- ErlHeapFragment *heap_frag;
- heap_frag = erts_dist_ext_trailer(mp->data.dist_ext);
- erts_cleanup_offheap(&heap_frag->off_heap);
- }
- erts_free_dist_ext_copy(dist_ext);
- message_free(mp);
+ erts_cleanup_messages(mp);
}
else
#endif
if (IS_TRACED_FL(rcvr, F_TRACE_RECEIVE)) {
/* Ahh... need to decode it in order to trace it... */
- ErlHeapFragment *mbuf;
- Eterm msg;
if (!(*rcvr_locks & ERTS_PROC_LOCK_MSGQ))
erts_smp_proc_unlock(rcvr, ERTS_PROC_LOCK_MSGQ);
- message_free(mp);
- msg = erts_msg_distext2heap(rcvr, rcvr_locks, &mbuf, &token, dist_ext);
- if (is_value(msg))
+ if (!erts_decode_dist_message(rcvr, *rcvr_locks, mp, 0))
+ erts_free_message(mp);
+ else {
+ Eterm msg = ERL_MESSAGE_TERM(mp);
+ token = ERL_MESSAGE_TOKEN(mp);
#ifdef USE_VM_PROBES
- if (DTRACE_ENABLED(message_queued)) {
- DTRACE_CHARBUF(receiver_name, DTRACE_TERM_BUF_SIZE);
-
- dtrace_proc_str(rcvr, receiver_name);
- if (token != NIL && token != am_have_dt_utag) {
- tok_label = signed_val(SEQ_TRACE_T_LABEL(token));
- tok_lastcnt = signed_val(SEQ_TRACE_T_LASTCNT(token));
- tok_serial = signed_val(SEQ_TRACE_T_SERIAL(token));
- }
- DTRACE6(message_queued,
- receiver_name, size_object(msg), rcvr->msg.len,
- tok_label, tok_lastcnt, tok_serial);
- }
+ if (DTRACE_ENABLED(message_queued)) {
+ DTRACE_CHARBUF(receiver_name, DTRACE_TERM_BUF_SIZE);
+
+ dtrace_proc_str(rcvr, receiver_name);
+ if (have_seqtrace(token)) {
+ tok_label = signed_val(SEQ_TRACE_T_LABEL(token));
+ tok_lastcnt = signed_val(SEQ_TRACE_T_LASTCNT(token));
+ tok_serial = signed_val(SEQ_TRACE_T_SERIAL(token));
+ }
+ DTRACE6(message_queued,
+ receiver_name, size_object(msg), rcvr->msg.len,
+ tok_label, tok_lastcnt, tok_serial);
+ }
#endif
- erts_queue_message(rcvr, rcvr_locks, mbuf, msg, token);
+ erts_queue_message(rcvr, rcvr_locks, mp, msg, token);
+ }
}
else {
/* Enqueue message on external format */
- ERL_MESSAGE_TERM(mp) = THE_NON_VALUE;
-#ifdef USE_VM_PROBES
- ERL_MESSAGE_DT_UTAG(mp) = NIL;
- if (token == am_have_dt_utag) {
- ERL_MESSAGE_TOKEN(mp) = NIL;
- } else {
-#endif
- ERL_MESSAGE_TOKEN(mp) = token;
-#ifdef USE_VM_PROBES
- }
-#endif
- mp->next = NULL;
-
#ifdef USE_VM_PROBES
if (DTRACE_ENABLED(message_queued)) {
DTRACE_CHARBUF(receiver_name, DTRACE_TERM_BUF_SIZE);
dtrace_proc_str(rcvr, receiver_name);
- if (token != NIL && token != am_have_dt_utag) {
+ if (have_seqtrace(token)) {
tok_label = signed_val(SEQ_TRACE_T_LABEL(token));
tok_lastcnt = signed_val(SEQ_TRACE_T_LASTCNT(token));
tok_serial = signed_val(SEQ_TRACE_T_SERIAL(token));
@@ -388,7 +348,7 @@ erts_queue_dist_message(Process *rcvr,
tok_label, tok_lastcnt, tok_serial);
}
#endif
- mp->data.dist_ext = dist_ext;
+
LINK_MESSAGE(rcvr, mp);
if (!(*rcvr_locks & ERTS_PROC_LOCK_MSGQ))
@@ -408,9 +368,9 @@ erts_queue_dist_message(Process *rcvr,
static Sint
queue_message(Process *c_p,
Process* receiver,
- ErtsProcLocks *receiver_locks,
erts_aint32_t *receiver_state,
- ErlHeapFragment* bp,
+ ErtsProcLocks *receiver_locks,
+ ErtsMessage* mp,
Eterm message,
Eterm seq_trace_token
#ifdef USE_VM_PROBES
@@ -419,31 +379,24 @@ queue_message(Process *c_p,
)
{
Sint res;
- ErlMessage* mp;
int locked_msgq = 0;
- erts_aint_t state;
-
-#ifndef ERTS_SMP
- ASSERT(bp != NULL || receiver->mbuf == NULL);
-#endif
+ erts_aint32_t state;
ERTS_SMP_LC_ASSERT(*receiver_locks == erts_proc_lc_my_proc_locks(receiver));
- mp = message_alloc();
-
- if (receiver_state)
- state = *receiver_state;
- else
- state = erts_smp_atomic32_read_acqb(&receiver->state);
-
#ifdef ERTS_SMP
- if (state & (ERTS_PSFLG_EXITING|ERTS_PSFLG_PENDING_EXIT))
- goto exiting;
-
if (!(*receiver_locks & ERTS_PROC_LOCK_MSGQ)) {
if (erts_smp_proc_trylock(receiver, ERTS_PROC_LOCK_MSGQ) == EBUSY) {
ErtsProcLocks need_locks = ERTS_PROC_LOCK_MSGQ;
+
+ if (receiver_state)
+ state = *receiver_state;
+ else
+ state = erts_smp_atomic32_read_nob(&receiver->state);
+ if (state & (ERTS_PSFLG_EXITING|ERTS_PSFLG_PENDING_EXIT))
+ goto exiting;
+
if (*receiver_locks & ERTS_PROC_LOCK_STATUS) {
erts_smp_proc_unlock(receiver, ERTS_PROC_LOCK_STATUS);
need_locks |= ERTS_PROC_LOCK_STATUS;
@@ -451,13 +404,12 @@ queue_message(Process *c_p,
erts_smp_proc_lock(receiver, need_locks);
}
locked_msgq = 1;
- state = erts_smp_atomic32_read_nob(&receiver->state);
- if (receiver_state)
- *receiver_state = state;
}
#endif
+ state = erts_smp_atomic32_read_nob(&receiver->state);
+
if (state & (ERTS_PSFLG_PENDING_EXIT|ERTS_PSFLG_EXITING)) {
#ifdef ERTS_SMP
exiting:
@@ -465,9 +417,7 @@ queue_message(Process *c_p,
/* Drop message if receiver is exiting or has a pending exit... */
if (locked_msgq)
erts_smp_proc_unlock(receiver, ERTS_PROC_LOCK_MSGQ);
- if (bp)
- free_message_buffer(bp);
- message_free(mp);
+ erts_cleanup_messages(mp);
return 0;
}
@@ -476,13 +426,9 @@ queue_message(Process *c_p,
#ifdef USE_VM_PROBES
ERL_MESSAGE_DT_UTAG(mp) = dt_utag;
#endif
- mp->next = NULL;
- mp->data.heap_frag = bp;
-#ifndef ERTS_SMP
res = receiver->msg.len;
-#else
- res = receiver->msg_inq.len;
+#ifdef ERTS_SMP
if (*receiver_locks & ERTS_PROC_LOCK_MAIN) {
/*
* We move 'in queue' to 'private queue' and place
@@ -492,7 +438,7 @@ queue_message(Process *c_p,
* we don't need to include the 'in queue' in
* the root set when garbage collecting.
*/
- res += receiver->msg.len;
+ res += receiver->msg_inq.len;
ERTS_SMP_MSGQ_MV_INQ2PRIVQ(receiver);
LINK_MESSAGE_PRIVQ(receiver, mp);
}
@@ -544,19 +490,19 @@ queue_message(Process *c_p,
void
#ifdef USE_VM_PROBES
erts_queue_message_probe(Process* receiver, ErtsProcLocks *receiver_locks,
- ErlHeapFragment* bp,
+ ErtsMessage* mp,
Eterm message, Eterm seq_trace_token, Eterm dt_utag)
#else
erts_queue_message(Process* receiver, ErtsProcLocks *receiver_locks,
- ErlHeapFragment* bp,
+ ErtsMessage* mp,
Eterm message, Eterm seq_trace_token)
#endif
{
queue_message(NULL,
receiver,
- receiver_locks,
NULL,
- bp,
+ receiver_locks,
+ mp,
message,
seq_trace_token
#ifdef USE_VM_PROBES
@@ -566,245 +512,37 @@ erts_queue_message(Process* receiver, ErtsProcLocks *receiver_locks,
}
void
-erts_link_mbuf_to_proc(struct process *proc, ErlHeapFragment *bp)
-{
- Eterm* htop = HEAP_TOP(proc);
-
- link_mbuf_to_proc(proc, bp);
- if (htop < HEAP_LIMIT(proc)) {
- *htop = make_pos_bignum_header(HEAP_LIMIT(proc)-htop-1);
- HEAP_TOP(proc) = HEAP_LIMIT(proc);
- }
-}
-
-/*
- * Moves content of message buffer attached to a message into a heap.
- * The message buffer is deallocated.
- */
-void
-erts_move_msg_mbuf_to_heap(Eterm** hpp, ErlOffHeap* off_heap, ErlMessage *msg)
+erts_link_mbuf_to_proc(Process *proc, ErlHeapFragment *first_bp)
{
- struct erl_off_heap_header* oh;
- Eterm term, token, *fhp, *hp;
- Sint offs;
- Uint sz;
- ErlHeapFragment *bp;
-#ifdef USE_VM_PROBES
- Eterm utag;
-#endif
-
-#ifdef HARD_DEBUG
- struct erl_off_heap_header* dbg_oh_start = off_heap->first;
- Eterm dbg_term, dbg_token;
- ErlHeapFragment *dbg_bp;
- Uint *dbg_hp, *dbg_thp_start;
- Uint dbg_term_sz, dbg_token_sz;
-#ifdef USE_VM_PROBES
- Eterm dbg_utag;
- Uint dbg_utag_sz;
-#endif
-#endif
-
- bp = msg->data.heap_frag;
- term = ERL_MESSAGE_TERM(msg);
- token = ERL_MESSAGE_TOKEN(msg);
-#ifdef USE_VM_PROBES
- utag = ERL_MESSAGE_DT_UTAG(msg);
-#endif
- if (!bp) {
-#ifdef USE_VM_PROBES
- ASSERT(is_immed(term) && is_immed(token) && is_immed(utag));
-#else
- ASSERT(is_immed(term) && is_immed(token));
-#endif
- return;
- }
-
-#ifdef HARD_DEBUG
- dbg_term_sz = size_object(term);
- dbg_token_sz = size_object(token);
- dbg_bp = new_message_buffer(dbg_term_sz + dbg_token_sz);
-#ifdef USE_VM_PROBES
- dbg_utag_sz = size_object(utag);
- dbg_bp = new_message_buffer(dbg_term_sz + dbg_token_sz + dbg_utag_sz );
-#endif
- /*ASSERT(dbg_term_sz + dbg_token_sz == erts_msg_used_frag_sz(msg));
- Copied size may be smaller due to removed SubBins's or garbage.
- Copied size may be larger due to duplicated shared terms.
- */
- dbg_hp = dbg_bp->mem;
- dbg_term = copy_struct(term, dbg_term_sz, &dbg_hp, &dbg_bp->off_heap);
- dbg_token = copy_struct(token, dbg_token_sz, &dbg_hp, &dbg_bp->off_heap);
-#ifdef USE_VM_PROBES
- dbg_utag = copy_struct(utag, dbg_utag_sz, &dbg_hp, &dbg_bp->off_heap);
-#endif
- dbg_thp_start = *hpp;
-#endif
-
- if (bp->next != NULL) {
- move_multi_frags(hpp, off_heap, bp, msg->m,
-#ifdef USE_VM_PROBES
- 3
-#else
- 2
-#endif
- );
- goto copy_done;
- }
-
- OH_OVERHEAD(off_heap, bp->off_heap.overhead);
- sz = bp->used_size;
-
- ASSERT(is_immed(term) || in_heapfrag(ptr_val(term),bp));
- ASSERT(is_immed(token) || in_heapfrag(ptr_val(token),bp));
-
- fhp = bp->mem;
- hp = *hpp;
- offs = hp - fhp;
-
- oh = NULL;
- while (sz--) {
- Uint cpy_sz;
- Eterm val = *fhp++;
-
- switch (primary_tag(val)) {
- case TAG_PRIMARY_IMMED1:
- *hp++ = val;
- break;
- case TAG_PRIMARY_LIST:
- case TAG_PRIMARY_BOXED:
- ASSERT(in_heapfrag(ptr_val(val), bp));
- *hp++ = offset_ptr(val, offs);
- break;
- case TAG_PRIMARY_HEADER:
- *hp++ = val;
- switch (val & _HEADER_SUBTAG_MASK) {
- case ARITYVAL_SUBTAG:
- break;
- case REFC_BINARY_SUBTAG:
- case FUN_SUBTAG:
- case EXTERNAL_PID_SUBTAG:
- case EXTERNAL_PORT_SUBTAG:
- case EXTERNAL_REF_SUBTAG:
- oh = (struct erl_off_heap_header*) (hp-1);
- cpy_sz = thing_arityval(val);
- goto cpy_words;
- default:
- cpy_sz = header_arity(val);
-
- cpy_words:
- ASSERT(sz >= cpy_sz);
- sz -= cpy_sz;
- while (cpy_sz >= 8) {
- cpy_sz -= 8;
- *hp++ = *fhp++;
- *hp++ = *fhp++;
- *hp++ = *fhp++;
- *hp++ = *fhp++;
- *hp++ = *fhp++;
- *hp++ = *fhp++;
- *hp++ = *fhp++;
- *hp++ = *fhp++;
- }
- switch (cpy_sz) {
- case 7: *hp++ = *fhp++;
- case 6: *hp++ = *fhp++;
- case 5: *hp++ = *fhp++;
- case 4: *hp++ = *fhp++;
- case 3: *hp++ = *fhp++;
- case 2: *hp++ = *fhp++;
- case 1: *hp++ = *fhp++;
- default: break;
+ if (first_bp) {
+ ErlHeapFragment *bp = first_bp;
+
+ while (1) {
+ /* Move any off_heap's into the process */
+ if (bp->off_heap.first != NULL) {
+ struct erl_off_heap_header** next_p = &bp->off_heap.first;
+ while (*next_p != NULL) {
+ next_p = &((*next_p)->next);
}
- if (oh) {
- /* Add to offheap list */
- oh->next = off_heap->first;
- off_heap->first = oh;
- ASSERT(*hpp <= (Eterm*)oh);
- ASSERT(hp > (Eterm*)oh);
- oh = NULL;
- }
- break;
+ *next_p = MSO(proc).first;
+ MSO(proc).first = bp->off_heap.first;
+ bp->off_heap.first = NULL;
+ OH_OVERHEAD(&(MSO(proc)), bp->off_heap.overhead);
}
- break;
+ MBUF_SIZE(proc) += bp->used_size;
+ if (!bp->next)
+ break;
+ bp = bp->next;
}
- }
-
- ASSERT(bp->used_size == hp - *hpp);
- *hpp = hp;
-
- if (is_not_immed(token)) {
- ASSERT(in_heapfrag(ptr_val(token), bp));
- ERL_MESSAGE_TOKEN(msg) = offset_ptr(token, offs);
-#ifdef HARD_DEBUG
- ASSERT(dbg_thp_start <= ptr_val(ERL_MESSAGE_TOKEN(msg)));
- ASSERT(hp > ptr_val(ERL_MESSAGE_TOKEN(msg)));
-#endif
- }
-
- if (is_not_immed(term)) {
- ASSERT(in_heapfrag(ptr_val(term),bp));
- ERL_MESSAGE_TERM(msg) = offset_ptr(term, offs);
-#ifdef HARD_DEBUG
- ASSERT(dbg_thp_start <= ptr_val(ERL_MESSAGE_TERM(msg)));
- ASSERT(hp > ptr_val(ERL_MESSAGE_TERM(msg)));
-#endif
- }
-#ifdef USE_VM_PROBES
- if (is_not_immed(utag)) {
- ASSERT(in_heapfrag(ptr_val(utag), bp));
- ERL_MESSAGE_DT_UTAG(msg) = offset_ptr(utag, offs);
-#ifdef HARD_DEBUG
- ASSERT(dbg_thp_start <= ptr_val(ERL_MESSAGE_DT_UTAG(msg)));
- ASSERT(hp > ptr_val(ERL_MESSAGE_DT_UTAG(msg)));
-#endif
- }
-#endif
-
-copy_done:
-#ifdef HARD_DEBUG
- {
- int i, j;
- ErlHeapFragment* frag;
- {
- struct erl_off_heap_header* dbg_oh = off_heap->first;
- i = j = 0;
- while (dbg_oh != dbg_oh_start) {
- dbg_oh = dbg_oh->next;
- i++;
- }
- for (frag=bp; frag; frag=frag->next) {
- dbg_oh = frag->off_heap.first;
- while (dbg_oh) {
- dbg_oh = dbg_oh->next;
- j++;
- }
- }
- ASSERT(i == j);
- }
+ /* Link the message buffer */
+ bp->next = MBUF(proc);
+ MBUF(proc) = first_bp;
}
-#endif
-
-
- bp->off_heap.first = NULL;
- free_message_buffer(bp);
- msg->data.heap_frag = NULL;
-
-#ifdef HARD_DEBUG
- ASSERT(eq(ERL_MESSAGE_TERM(msg), dbg_term));
- ASSERT(eq(ERL_MESSAGE_TOKEN(msg), dbg_token));
-#ifdef USE_VM_PROBES
- ASSERT(eq(ERL_MESSAGE_DT_UTAG(msg), dbg_utag));
-#endif
- free_message_buffer(dbg_bp);
-#endif
-
}
-
Uint
-erts_msg_attached_data_size_aux(ErlMessage *msg)
+erts_msg_attached_data_size_aux(ErtsMessage *msg)
{
Sint sz;
ASSERT(is_non_value(ERL_MESSAGE_TERM(msg)));
@@ -833,29 +571,87 @@ erts_msg_attached_data_size_aux(ErlMessage *msg)
return sz;
}
-void
-erts_move_msg_attached_data_to_heap(ErtsHeapFactory* factory,
- ErlMessage *msg)
+ErtsMessage *
+erts_try_alloc_message_on_heap(Process *pp,
+ erts_aint32_t *psp,
+ ErtsProcLocks *plp,
+ Uint sz,
+ Eterm **hpp,
+ ErlOffHeap **ohpp,
+ int *on_heap_p)
{
- if (is_value(ERL_MESSAGE_TERM(msg)))
- erts_move_msg_mbuf_to_heap(&factory->hp, factory->off_heap, msg);
- else if (msg->data.dist_ext) {
- ASSERT(msg->data.dist_ext->heap_size >= 0);
- if (is_not_nil(ERL_MESSAGE_TOKEN(msg))) {
- ErlHeapFragment *heap_frag;
- heap_frag = erts_dist_ext_trailer(msg->data.dist_ext);
- ERL_MESSAGE_TOKEN(msg) = copy_struct(ERL_MESSAGE_TOKEN(msg),
- heap_frag->used_size,
- &factory->hp,
- factory->off_heap);
- erts_cleanup_offheap(&heap_frag->off_heap);
+#ifdef ERTS_SMP
+ int locked_main = 0;
+#endif
+ ErtsMessage *mp;
+
+ ASSERT(!(*psp & ERTS_PSFLG_OFF_HEAP_MSGQ));
+
+ if (
+#if defined(ERTS_SMP)
+ *plp & ERTS_PROC_LOCK_MAIN
+#else
+ 1
+#endif
+ ) {
+#ifdef ERTS_SMP
+ try_on_heap:
+#endif
+ if ((*psp & (ERTS_PSFLG_EXITING|ERTS_PSFLG_PENDING_EXIT))
+ || (pp->flags & F_DISABLE_GC)
+ || HEAP_LIMIT(pp) - HEAP_TOP(pp) <= sz) {
+ /*
+ * The heap is either potentially in an inconsistent
+ * state, or not large enough.
+ */
+#ifdef ERTS_SMP
+ if (locked_main) {
+ *plp &= ~ERTS_PROC_LOCK_MAIN;
+ erts_smp_proc_unlock(pp, ERTS_PROC_LOCK_MAIN);
+ }
+#endif
+ goto in_message_fragment;
}
- ERL_MESSAGE_TERM(msg) = erts_decode_dist_ext(factory,
- msg->data.dist_ext);
- erts_free_dist_ext_copy(msg->data.dist_ext);
- msg->data.dist_ext = NULL;
+
+ *hpp = HEAP_TOP(pp);
+ HEAP_TOP(pp) = *hpp + sz;
+ *ohpp = &MSO(pp);
+ mp = erts_alloc_message(0, NULL);
+ mp->data.attached = NULL;
+ *on_heap_p = !0;
+ }
+#ifdef ERTS_SMP
+ else if (erts_smp_proc_trylock(pp, ERTS_PROC_LOCK_MAIN) == 0) {
+ locked_main = 1;
+ *psp = erts_smp_atomic32_read_nob(&pp->state);
+ *plp |= ERTS_PROC_LOCK_MAIN;
+ goto try_on_heap;
}
- /* else: bad external detected when calculating size */
+#endif
+ else {
+ in_message_fragment:
+ if (!((*psp) & ERTS_PSFLG_ON_HEAP_MSGQ)) {
+ mp = erts_alloc_message(sz, hpp);
+ *ohpp = sz == 0 ? NULL : &mp->hfrag.off_heap;
+ }
+ else {
+ mp = erts_alloc_message(0, NULL);
+ if (!sz) {
+ *hpp = NULL;
+ *ohpp = NULL;
+ }
+ else {
+ ErlHeapFragment *bp;
+ bp = new_message_buffer(sz);
+ *hpp = &bp->mem[0];
+ mp->data.heap_frag = bp;
+ *ohpp = &bp->off_heap;
+ }
+ }
+ *on_heap_p = 0;
+ }
+
+ return mp;
}
/*
@@ -870,7 +666,8 @@ erts_send_message(Process* sender,
unsigned flags)
{
Uint msize;
- ErlHeapFragment* bp = NULL;
+ ErtsMessage* mp;
+ ErlOffHeap *ohp;
Eterm token = NIL;
Sint res = 0;
#ifdef USE_VM_PROBES
@@ -879,67 +676,96 @@ erts_send_message(Process* sender,
Sint tok_label = 0;
Sint tok_lastcnt = 0;
Sint tok_serial = 0;
+ Eterm utag = NIL;
+#endif
+ erts_aint32_t receiver_state;
+#ifdef SHCOPY_SEND
+ erts_shcopy_t info;
#endif
BM_STOP_TIMER(system);
BM_MESSAGE(message,sender,receiver);
BM_START_TIMER(send);
- #ifdef USE_VM_PROBES
+#ifdef USE_VM_PROBES
*sender_name = *receiver_name = '\0';
- if (DTRACE_ENABLED(message_send)) {
+ if (DTRACE_ENABLED(message_send)) {
erts_snprintf(sender_name, sizeof(DTRACE_CHARBUF_NAME(sender_name)),
"%T", sender->common.id);
erts_snprintf(receiver_name, sizeof(DTRACE_CHARBUF_NAME(receiver_name)),
"%T", receiver->common.id);
}
#endif
+
+ receiver_state = erts_smp_atomic32_read_nob(&receiver->state);
+
if (SEQ_TRACE_TOKEN(sender) != NIL && !(flags & ERTS_SND_FLG_NO_SEQ_TRACE)) {
Eterm* hp;
Eterm stoken = SEQ_TRACE_TOKEN(sender);
Uint seq_trace_size = 0;
#ifdef USE_VM_PROBES
Uint dt_utag_size = 0;
- Eterm utag = NIL;
-#endif
-
- BM_SWAP_TIMER(send,size);
- msize = size_object(message);
- BM_SWAP_TIMER(size,send);
-
-#ifdef USE_VM_PROBES
- if (stoken != am_have_dt_utag) {
#endif
-
+ BM_SWAP_TIMER(send,size);
+
+ /* SHCOPY corrupts the heap between
+ * copy_shared_calculate, and
+ * copy_shared_perform. (it inserts move_markers like the gc).
+ * Make sure we don't use the heap between those instances.
+ */
+ if (have_seqtrace(stoken)) {
seq_trace_update_send(sender);
seq_trace_output(stoken, message, SEQ_TRACE_SEND,
receiver->common.id, sender);
seq_trace_size = 6; /* TUPLE5 */
-#ifdef USE_VM_PROBES
- }
- if (DT_UTAG_FLAGS(sender) & DT_UTAG_SPREADING) {
- dt_utag_size = size_object(DT_UTAG(sender));
- } else if (stoken == am_have_dt_utag ) {
- stoken = NIL;
}
+#ifdef USE_VM_PROBES
+ if (DT_UTAG_FLAGS(sender) & DT_UTAG_SPREADING) {
+ dt_utag_size = size_object(DT_UTAG(sender));
+ } else if (stoken == am_have_dt_utag ) {
+ stoken = NIL;
+ }
#endif
- bp = new_message_buffer(msize + seq_trace_size
+#ifdef SHCOPY_SEND
+ INITIALIZE_SHCOPY(info);
+ msize = copy_shared_calculate(message, &info);
+#else
+ msize = size_object(message);
+#endif
+ BM_SWAP_TIMER(size,send);
+
+ mp = erts_alloc_message_heap_state(receiver,
+ &receiver_state,
+ receiver_locks,
+ (msize
#ifdef USE_VM_PROBES
- + dt_utag_size
+ + dt_utag_size
#endif
- );
- hp = bp->mem;
+ + seq_trace_size),
+ &hp,
+ &ohp);
BM_SWAP_TIMER(send,copy);
- token = copy_struct(stoken,
- seq_trace_size,
- &hp,
- &bp->off_heap);
- message = copy_struct(message, msize, &hp, &bp->off_heap);
+#ifdef SHCOPY_SEND
+ if (is_not_immed(message))
+ message = copy_shared_perform(message, msize, &info, &hp, ohp);
+ DESTROY_SHCOPY(info);
+#else
+ if (is_not_immed(message))
+ message = copy_struct(message, msize, &hp, ohp);
+#endif
+ if (is_immed(stoken))
+ token = stoken;
+ else
+ token = copy_struct(stoken, seq_trace_size, &hp, ohp);
+
#ifdef USE_VM_PROBES
if (DT_UTAG_FLAGS(sender) & DT_UTAG_SPREADING) {
- utag = copy_struct(DT_UTAG(sender), dt_utag_size, &hp, &bp->off_heap);
+ if (is_immed(DT_UTAG(sender)))
+ utag = DT_UTAG(sender);
+ else
+ utag = copy_struct(DT_UTAG(sender), dt_utag_size, ohp);
#ifdef DTRACE_TAG_HARDDEBUG
erts_fprintf(stderr,
"Dtrace -> (%T) Spreading tag (%T) with "
@@ -952,7 +778,7 @@ erts_send_message(Process* sender,
#ifdef USE_VM_PROBES
if (DTRACE_ENABLED(message_send)) {
- if (stoken != NIL && stoken != am_have_dt_utag) {
+ if (have_seqtrace(stoken)) {
tok_label = signed_val(SEQ_TRACE_T_LABEL(stoken));
tok_lastcnt = signed_val(SEQ_TRACE_T_LASTCNT(stoken));
tok_serial = signed_val(SEQ_TRACE_T_SERIAL(stoken));
@@ -961,103 +787,63 @@ erts_send_message(Process* sender,
msize, tok_label, tok_lastcnt, tok_serial);
}
#endif
- res = queue_message(NULL,
- receiver,
- receiver_locks,
- NULL,
- bp,
- message,
- token
-#ifdef USE_VM_PROBES
- , utag
-#endif
- );
- BM_SWAP_TIMER(send,system);
- } else if (sender == receiver) {
- /* Drop message if receiver has a pending exit ... */
-#ifdef ERTS_SMP
- ErtsProcLocks need_locks = (~(*receiver_locks)
- & (ERTS_PROC_LOCK_MSGQ
- | ERTS_PROC_LOCK_STATUS));
- if (need_locks) {
- *receiver_locks |= need_locks;
- if (erts_smp_proc_trylock(receiver, need_locks) == EBUSY) {
- if (need_locks == ERTS_PROC_LOCK_MSGQ) {
- erts_smp_proc_unlock(receiver, ERTS_PROC_LOCK_STATUS);
- need_locks = ERTS_PROC_LOCK_MSGQ|ERTS_PROC_LOCK_STATUS;
- }
- erts_smp_proc_lock(receiver, need_locks);
- }
+ } else {
+ Eterm *hp;
+
+ if (receiver == sender && !(receiver_state & ERTS_PSFLG_OFF_HEAP_MSGQ)) {
+ mp = erts_alloc_message(0, NULL);
+ msize = 0;
}
- if (!ERTS_PROC_PENDING_EXIT(receiver))
+ else {
+ BM_SWAP_TIMER(send,size);
+#ifdef SHCOPY_SEND
+ INITIALIZE_SHCOPY(info);
+ msize = copy_shared_calculate(message, &info);
+#else
+ msize = size_object(message);
#endif
- {
- ErlMessage* mp = message_alloc();
-
- DTRACE6(message_send, sender_name, receiver_name,
- size_object(message), tok_label, tok_lastcnt, tok_serial);
- mp->data.attached = NULL;
- ERL_MESSAGE_TERM(mp) = message;
- ERL_MESSAGE_TOKEN(mp) = NIL;
-#ifdef USE_VM_PROBES
- ERL_MESSAGE_DT_UTAG(mp) = NIL;
+ BM_SWAP_TIMER(size,send);
+
+ mp = erts_alloc_message_heap_state(receiver,
+ &receiver_state,
+ receiver_locks,
+ msize,
+ &hp,
+ &ohp);
+ BM_SWAP_TIMER(send,copy);
+#ifdef SHCOPY_SEND
+ if (is_not_immed(message))
+ message = copy_shared_perform(message, msize, &info, &hp, ohp);
+ DESTROY_SHCOPY(info);
+#else
+ if (is_not_immed(message))
+ message = copy_struct(message, msize, &hp, ohp);
#endif
- mp->next = NULL;
- /*
- * We move 'in queue' to 'private queue' and place
- * message at the end of 'private queue' in order
- * to ensure that the 'in queue' doesn't contain
- * references into the heap. By ensuring this,
- * we don't need to include the 'in queue' in
- * the root set when garbage collecting.
- */
-
- ERTS_SMP_MSGQ_MV_INQ2PRIVQ(receiver);
- LINK_MESSAGE_PRIVQ(receiver, mp);
-
- res = receiver->msg.len;
-
- if (IS_TRACED_FL(receiver, F_TRACE_RECEIVE)) {
- trace_receive(receiver, message);
- }
+ BM_MESSAGE_COPIED(msz);
+ BM_SWAP_TIMER(copy,send);
}
- BM_SWAP_TIMER(send,system);
- } else {
- ErlOffHeap *ohp;
- Eterm *hp;
- erts_aint32_t state;
-
- BM_SWAP_TIMER(send,size);
- msize = size_object(message);
- BM_SWAP_TIMER(size,send);
- hp = erts_alloc_message_heap_state(msize,
- &bp,
- &ohp,
- receiver,
- receiver_locks,
- &state);
- BM_SWAP_TIMER(send,copy);
- message = copy_struct(message, msize, &hp, ohp);
- BM_MESSAGE_COPIED(msz);
- BM_SWAP_TIMER(copy,send);
DTRACE6(message_send, sender_name, receiver_name,
msize, tok_label, tok_lastcnt, tok_serial);
- res = queue_message(sender,
- receiver,
- receiver_locks,
- &state,
- bp,
- message,
- token
+ }
+
+ res = queue_message(sender,
+ receiver,
+ &receiver_state,
+ receiver_locks,
+ mp,
+ message,
+ token
#ifdef USE_VM_PROBES
- , NIL
+ , utag
#endif
- );
- BM_SWAP_TIMER(send,system);
- }
- return res;
+ );
+
+ BM_SWAP_TIMER(send,system);
+
+ return res;
}
+
/*
* This function delivers an EXIT message to a process
* which is trapping EXITs.
@@ -1075,46 +861,572 @@ erts_deliver_exit_message(Eterm from, Process *to, ErtsProcLocks *to_locksp,
Uint sz_from;
Eterm* hp;
Eterm temptoken;
- ErlHeapFragment* bp = NULL;
-
- if (token != NIL
-#ifdef USE_VM_PROBES
- && token != am_have_dt_utag
+ ErtsMessage* mp;
+ ErlOffHeap *ohp;
+#ifdef SHCOPY_SEND
+ erts_shcopy_t info;
#endif
- ) {
+ if (have_seqtrace(token)) {
ASSERT(is_tuple(token));
- sz_reason = size_object(reason);
sz_token = size_object(token);
sz_from = size_object(from);
- bp = new_message_buffer(sz_reason + sz_from + sz_token + 4);
- hp = bp->mem;
- mess = copy_struct(reason, sz_reason, &hp, &bp->off_heap);
- from_copy = copy_struct(from, sz_from, &hp, &bp->off_heap);
+#ifdef SHCOPY_SEND
+ INITIALIZE_SHCOPY(info);
+ sz_reason = copy_shared_calculate(reason, &info);
+#else
+ sz_reason = size_object(reason);
+#endif
+ mp = erts_alloc_message_heap(to, to_locksp,
+ sz_reason + sz_from + sz_token + 4,
+ &hp, &ohp);
+#ifdef SHCOPY_SEND
+ mess = copy_shared_perform(reason, sz_reason, &info, &hp, ohp);
+ DESTROY_SHCOPY(info);
+#else
+ mess = copy_struct(reason, sz_reason, &hp, ohp);
+#endif
+ from_copy = copy_struct(from, sz_from, &hp, ohp);
save = TUPLE3(hp, am_EXIT, from_copy, mess);
hp += 4;
/* the trace token must in this case be updated by the caller */
seq_trace_output(token, save, SEQ_TRACE_SEND, to->common.id, NULL);
- temptoken = copy_struct(token, sz_token, &hp, &bp->off_heap);
- erts_queue_message(to, to_locksp, bp, save, temptoken);
+ temptoken = copy_struct(token, sz_token, &hp, ohp);
+ erts_queue_message(to, to_locksp, mp, save, temptoken);
} else {
- ErlOffHeap *ohp;
- sz_reason = size_object(reason);
sz_from = IS_CONST(from) ? 0 : size_object(from);
+#ifdef SHCOPY_SEND
+ INITIALIZE_SHCOPY(info);
+ sz_reason = copy_shared_calculate(reason, &info);
+#else
+ sz_reason = size_object(reason);
+#endif
+ mp = erts_alloc_message_heap(to, to_locksp,
+ sz_reason+sz_from+4, &hp, &ohp);
- hp = erts_alloc_message_heap(sz_reason+sz_from+4,
- &bp,
- &ohp,
- to,
- to_locksp);
-
+#ifdef SHCOPY_SEND
+ mess = copy_shared_perform(reason, sz_reason, &info, &hp, ohp);
+ DESTROY_SHCOPY(info);
+#else
mess = copy_struct(reason, sz_reason, &hp, ohp);
+#endif
from_copy = (IS_CONST(from)
? from
: copy_struct(from, sz_from, &hp, ohp));
save = TUPLE3(hp, am_EXIT, from_copy, mess);
- erts_queue_message(to, to_locksp, bp, save, NIL);
+ erts_queue_message(to, to_locksp, mp, save, NIL);
+ }
+}
+
+void erts_save_message_in_proc(Process *p, ErtsMessage *msgp)
+{
+ ErlHeapFragment *hfp;
+
+ if (msgp->data.attached == ERTS_MSG_COMBINED_HFRAG)
+ hfp = &msgp->hfrag;
+ else if (msgp->data.attached) {
+ hfp = msgp->data.heap_frag;
+ }
+ else {
+ erts_free_message(msgp);
+ return; /* Nothing to save */
+ }
+
+ while (1) {
+ struct erl_off_heap_header *ohhp = hfp->off_heap.first;
+ if (ohhp) {
+ for ( ; ohhp->next; ohhp = ohhp->next)
+ ;
+ ohhp->next = p->off_heap.first;
+ p->off_heap.first = hfp->off_heap.first;
+ hfp->off_heap.first = NULL;
+ }
+ p->off_heap.overhead += hfp->off_heap.overhead;
+ hfp->off_heap.overhead = 0;
+ p->mbuf_sz += hfp->used_size;
+
+ if (!hfp->next)
+ break;
+ hfp = hfp->next;
+ }
+
+ msgp->next = p->msg_frag;
+ p->msg_frag = msgp;
+}
+
+Sint
+erts_move_messages_off_heap(Process *c_p)
+{
+ int reds = 1;
+ /*
+ * Move all messages off heap. This *only* occurs when the
+ * process had off heap message disabled and just enabled
+ * it...
+ */
+ ErtsMessage *mp;
+
+ reds += c_p->msg.len / 10;
+
+ ASSERT(erts_smp_atomic32_read_nob(&c_p->state)
+ & ERTS_PSFLG_OFF_HEAP_MSGQ);
+ ASSERT(c_p->flags & F_OFF_HEAP_MSGQ_CHNG);
+
+ for (mp = c_p->msg.first; mp; mp = mp->next) {
+ Uint msg_sz, token_sz;
+#ifdef USE_VM_PROBES
+ Uint utag_sz;
+#endif
+ Eterm *hp;
+ ErlHeapFragment *hfrag;
+
+ if (mp->data.attached)
+ continue;
+
+ if (is_immed(ERL_MESSAGE_TERM(mp))
+#ifdef USE_VM_PROBES
+ && is_immed(ERL_MESSAGE_DT_UTAG(mp))
+#endif
+ && is_not_immed(ERL_MESSAGE_TOKEN(mp)))
+ continue;
+
+ /*
+ * The message refers into the heap. Copy the message
+ * from the heap into a heap fragment and attach
+ * it to the message...
+ */
+ msg_sz = size_object(ERL_MESSAGE_TERM(mp));
+#ifdef USE_VM_PROBES
+ utag_sz = size_object(ERL_MESSAGE_DT_UTAG(mp));
+#endif
+ token_sz = size_object(ERL_MESSAGE_TOKEN(mp));
+
+ hfrag = new_message_buffer(msg_sz
+#ifdef USE_VM_PROBES
+ + utag_sz
+#endif
+ + token_sz);
+ hp = hfrag->mem;
+ if (is_not_immed(ERL_MESSAGE_TERM(mp)))
+ ERL_MESSAGE_TERM(mp) = copy_struct(ERL_MESSAGE_TERM(mp),
+ msg_sz, &hp,
+ &hfrag->off_heap);
+ if (is_not_immed(ERL_MESSAGE_TOKEN(mp)))
+ ERL_MESSAGE_TOKEN(mp) = copy_struct(ERL_MESSAGE_TOKEN(mp),
+ token_sz, &hp,
+ &hfrag->off_heap);
+#ifdef USE_VM_PROBES
+ if (is_not_immed(ERL_MESSAGE_DT_UTAG(mp)))
+ ERL_MESSAGE_DT_UTAG(mp) = copy_struct(ERL_MESSAGE_DT_UTAG(mp),
+ utag_sz, &hp,
+ &hfrag->off_heap);
+#endif
+ mp->data.heap_frag = hfrag;
+ reds += 1;
+ }
+
+ return reds;
+}
+
+Sint
+erts_complete_off_heap_message_queue_change(Process *c_p)
+{
+ int reds = 1;
+
+ ERTS_SMP_LC_ASSERT(ERTS_PROC_LOCK_MAIN == erts_proc_lc_my_proc_locks(c_p));
+ ASSERT(c_p->flags & F_OFF_HEAP_MSGQ_CHNG);
+ ASSERT(erts_smp_atomic32_read_nob(&c_p->state) & ERTS_PSFLG_OFF_HEAP_MSGQ);
+
+ /*
+ * This job was first initiated when the process changed to off heap
+ * message queue management. Since then ERTS_PSFLG_OFF_HEAP_MSGQ
+ * has been set. However, the management state might have been changed
+ * again (multiple times) since then. Check users last requested state
+ * (the flags F_OFF_HEAP_MSGQ, and F_ON_HEAP_MSGQ), and make the state
+ * consistent with that.
+ */
+
+ if (!(c_p->flags & F_OFF_HEAP_MSGQ))
+ erts_smp_atomic32_read_band_nob(&c_p->state,
+ ~ERTS_PSFLG_OFF_HEAP_MSGQ);
+ else {
+ reds += 2;
+ erts_smp_proc_lock(c_p, ERTS_PROC_LOCK_MSGQ);
+ ERTS_SMP_MSGQ_MV_INQ2PRIVQ(c_p);
+ erts_smp_proc_unlock(c_p, ERTS_PROC_LOCK_MSGQ);
+ reds += erts_move_messages_off_heap(c_p);
+ }
+ c_p->flags &= ~F_OFF_HEAP_MSGQ_CHNG;
+ return reds;
+}
+
+typedef struct {
+ Eterm pid;
+ ErtsThrPrgrLaterOp lop;
+} ErtsChangeOffHeapMessageQueue;
+
+static void
+change_off_heap_msgq(void *vcohmq)
+{
+ ErtsChangeOffHeapMessageQueue *cohmq;
+ /*
+ * Now we've waited thread progress which ensures that all
+ * messages to the process are enqueued off heap. Schedule
+ * completion of this change as a system task on the process
+ * itself. This in order to avoid lock contention on its
+ * main lock. We will be called in
+ * erts_complete_off_heap_message_queue_change() (above) when
+ * the system task has been selected for execution.
+ */
+ cohmq = (ErtsChangeOffHeapMessageQueue *) vcohmq;
+ erts_schedule_complete_off_heap_message_queue_change(cohmq->pid);
+ erts_free(ERTS_ALC_T_MSGQ_CHNG, vcohmq);
+}
+
+Eterm
+erts_change_message_queue_management(Process *c_p, Eterm new_state)
+{
+ Eterm res;
+
+#ifdef DEBUG
+ if (c_p->flags & F_OFF_HEAP_MSGQ) {
+ ASSERT(erts_smp_atomic32_read_nob(&c_p->state)
+ & ERTS_PSFLG_OFF_HEAP_MSGQ);
+ }
+ else {
+ if (c_p->flags & F_OFF_HEAP_MSGQ_CHNG) {
+ ASSERT(erts_smp_atomic32_read_nob(&c_p->state)
+ & ERTS_PSFLG_OFF_HEAP_MSGQ);
+ }
+ else {
+ ASSERT(!(erts_smp_atomic32_read_nob(&c_p->state)
+ & ERTS_PSFLG_OFF_HEAP_MSGQ));
+ }
+ }
+#endif
+
+ switch (c_p->flags & (F_OFF_HEAP_MSGQ|F_ON_HEAP_MSGQ)) {
+
+ case F_OFF_HEAP_MSGQ:
+ res = am_off_heap;
+
+ switch (new_state) {
+ case am_off_heap:
+ break;
+ case am_on_heap:
+ c_p->flags |= F_ON_HEAP_MSGQ;
+ erts_smp_atomic32_read_bor_nob(&c_p->state,
+ ERTS_PSFLG_ON_HEAP_MSGQ);
+ /* fall through */
+ case am_mixed:
+ c_p->flags &= ~F_OFF_HEAP_MSGQ;
+ /*
+ * We are not allowed to clear ERTS_PSFLG_OFF_HEAP_MSGQ
+ * if a off heap change is ongoing. It will be adjusted
+ * when the change completes...
+ */
+ if (!(c_p->flags & F_OFF_HEAP_MSGQ_CHNG)) {
+ /* Safe to clear ERTS_PSFLG_OFF_HEAP_MSGQ... */
+ erts_smp_atomic32_read_band_nob(&c_p->state,
+ ~ERTS_PSFLG_OFF_HEAP_MSGQ);
+ }
+ break;
+ default:
+ res = THE_NON_VALUE; /* badarg */
+ break;
+ }
+ break;
+
+ case F_ON_HEAP_MSGQ:
+ res = am_on_heap;
+
+ switch (new_state) {
+ case am_on_heap:
+ break;
+ case am_mixed:
+ c_p->flags &= ~F_ON_HEAP_MSGQ;
+ erts_smp_atomic32_read_band_nob(&c_p->state,
+ ~ERTS_PSFLG_ON_HEAP_MSGQ);
+ break;
+ case am_off_heap:
+ c_p->flags &= ~F_ON_HEAP_MSGQ;
+ erts_smp_atomic32_read_band_nob(&c_p->state,
+ ~ERTS_PSFLG_ON_HEAP_MSGQ);
+ goto change_to_off_heap;
+ default:
+ res = THE_NON_VALUE; /* badarg */
+ break;
+ }
+ break;
+
+ case 0:
+ res = am_mixed;
+
+ switch (new_state) {
+ case am_mixed:
+ break;
+ case am_on_heap:
+ c_p->flags |= F_ON_HEAP_MSGQ;
+ erts_smp_atomic32_read_bor_nob(&c_p->state,
+ ERTS_PSFLG_ON_HEAP_MSGQ);
+ break;
+ case am_off_heap:
+ goto change_to_off_heap;
+ default:
+ res = THE_NON_VALUE; /* badarg */
+ break;
+ }
+ break;
+
+ default:
+ res = am_error;
+ ERTS_INTERNAL_ERROR("Inconsistent message queue management state");
+ break;
+ }
+
+ return res;
+
+change_to_off_heap:
+
+ c_p->flags |= F_OFF_HEAP_MSGQ;
+
+ /*
+ * We do not have to schedule a change if
+ * we have an ongoing off heap change...
+ */
+ if (!(c_p->flags & F_OFF_HEAP_MSGQ_CHNG)) {
+ ErtsChangeOffHeapMessageQueue *cohmq;
+ /*
+ * Need to set ERTS_PSFLG_OFF_HEAP_MSGQ and wait
+ * thread progress before completing the change in
+ * order to ensure that all senders observe that
+ * messages should be passed off heap. When the
+ * change has completed, GC does not need to inspect
+ * the message queue at all.
+ */
+ erts_smp_atomic32_read_bor_nob(&c_p->state,
+ ERTS_PSFLG_OFF_HEAP_MSGQ);
+ c_p->flags |= F_OFF_HEAP_MSGQ_CHNG;
+ cohmq = erts_alloc(ERTS_ALC_T_MSGQ_CHNG,
+ sizeof(ErtsChangeOffHeapMessageQueue));
+ cohmq->pid = c_p->common.id;
+ erts_schedule_thr_prgr_later_op(change_off_heap_msgq,
+ (void *) cohmq,
+ &cohmq->lop);
+ }
+
+ return res;
+}
+
+int
+erts_decode_dist_message(Process *proc, ErtsProcLocks proc_locks,
+ ErtsMessage *msgp, int force_off_heap)
+{
+ ErtsHeapFactory factory;
+ Eterm msg;
+ ErlHeapFragment *bp;
+ Sint need;
+ int decode_in_heap_frag;
+
+ decode_in_heap_frag = (force_off_heap
+ || !(proc_locks & ERTS_PROC_LOCK_MAIN)
+ || (proc->flags & F_OFF_HEAP_MSGQ));
+
+ if (msgp->data.dist_ext->heap_size >= 0)
+ need = msgp->data.dist_ext->heap_size;
+ else {
+ need = erts_decode_dist_ext_size(msgp->data.dist_ext);
+ if (need < 0) {
+ /* bad msg; remove it... */
+ if (is_not_immed(ERL_MESSAGE_TOKEN(msgp))) {
+ bp = erts_dist_ext_trailer(msgp->data.dist_ext);
+ erts_cleanup_offheap(&bp->off_heap);
+ }
+ erts_free_dist_ext_copy(msgp->data.dist_ext);
+ msgp->data.dist_ext = NULL;
+ return 0;
+ }
+
+ msgp->data.dist_ext->heap_size = need;
+ }
+
+ if (is_not_immed(ERL_MESSAGE_TOKEN(msgp))) {
+ bp = erts_dist_ext_trailer(msgp->data.dist_ext);
+ need += bp->used_size;
+ }
+
+ if (decode_in_heap_frag)
+ erts_factory_heap_frag_init(&factory, new_message_buffer(need));
+ else
+ erts_factory_proc_prealloc_init(&factory, proc, need);
+
+ ASSERT(msgp->data.dist_ext->heap_size >= 0);
+ if (is_not_immed(ERL_MESSAGE_TOKEN(msgp))) {
+ ErlHeapFragment *heap_frag;
+ heap_frag = erts_dist_ext_trailer(msgp->data.dist_ext);
+ ERL_MESSAGE_TOKEN(msgp) = copy_struct(ERL_MESSAGE_TOKEN(msgp),
+ heap_frag->used_size,
+ &factory.hp,
+ factory.off_heap);
+ erts_cleanup_offheap(&heap_frag->off_heap);
}
+
+ msg = erts_decode_dist_ext(&factory, msgp->data.dist_ext);
+ ERL_MESSAGE_TERM(msgp) = msg;
+ erts_free_dist_ext_copy(msgp->data.dist_ext);
+ msgp->data.attached = NULL;
+
+ if (is_non_value(msg)) {
+ erts_factory_undo(&factory);
+ return 0;
+ }
+
+ erts_factory_trim_and_close(&factory, msgp->m,
+ ERL_MESSAGE_REF_ARRAY_SZ);
+
+ ASSERT(!msgp->data.heap_frag);
+
+ if (decode_in_heap_frag)
+ msgp->data.heap_frag = factory.heap_frags;
+
+ return 1;
+}
+
+/*
+ * ERTS_INSPECT_MSGQ_KEEP_OH_MSGS == 0 will move off heap messages
+ * into the heap of the inspected process if off_heap_message_queue
+ * is false when process_info(_, messages) is called. That is, the
+ * following GC will have more data in the rootset compared to the
+ * scenario when process_info(_, messages) had not been called.
+ *
+ * ERTS_INSPECT_MSGQ_KEEP_OH_MSGS != 0 will keep off heap messages
+ * off heap when process_info(_, messages) is called regardless of
+ * the off_heap_message_queue setting of the process. That is, it
+ * will change the following execution of the process as little as
+ * possible.
+ */
+#define ERTS_INSPECT_MSGQ_KEEP_OH_MSGS 1
+
+Uint
+erts_prep_msgq_for_inspection(Process *c_p, Process *rp,
+ ErtsProcLocks rp_locks, ErtsMessageInfo *mip)
+{
+ Uint tot_heap_size;
+ ErtsMessage* mp;
+ Sint i;
+ int self_on_heap;
+
+ /*
+ * Prepare the message queue for inspection
+ * by process_info().
+ *
+ *
+ * - Decode all messages on external format
+ * - Remove all corrupt dist messages from queue
+ * - Save pointer to, and heap size need of each
+ * message in the mip array.
+ * - Return total heap size need for all messages
+ * that needs to be copied.
+ *
+ * If ERTS_INSPECT_MSGQ_KEEP_OH_MSGS == 0:
+ * - In case off heap messages is disabled and
+ * we are inspecting our own queue, move all
+ * off heap data into the heap.
+ */
+
+ self_on_heap = c_p == rp && !(c_p->flags & F_OFF_HEAP_MSGQ);
+
+ tot_heap_size = 0;
+ i = 0;
+ mp = rp->msg.first;
+ while (mp) {
+ Eterm msg = ERL_MESSAGE_TERM(mp);
+
+ mip[i].size = 0;
+
+ if (is_non_value(msg)) {
+ /* Dist message on external format; decode it... */
+ if (mp->data.attached)
+ erts_decode_dist_message(rp, rp_locks, mp,
+ ERTS_INSPECT_MSGQ_KEEP_OH_MSGS);
+
+ msg = ERL_MESSAGE_TERM(mp);
+
+ if (is_non_value(msg)) {
+ ErtsMessage **mpp;
+ ErtsMessage *bad_mp = mp;
+ /*
+ * Bad distribution message; remove
+ * it from the queue...
+ */
+ ASSERT(!mp->data.attached);
+
+ mpp = i == 0 ? &rp->msg.first : &mip[i-1].msgp->next;
+
+ if (rp->msg.save == &bad_mp->next)
+ rp->msg.save = mpp;
+ if (rp->msg.last == &bad_mp->next)
+ rp->msg.last = mpp;
+ mp = mp->next;
+ *mpp = mp;
+ rp->msg.len--;
+ bad_mp->next = NULL;
+ erts_cleanup_messages(bad_mp);
+ continue;
+ }
+ }
+
+ ASSERT(is_value(msg));
+
+#if ERTS_INSPECT_MSGQ_KEEP_OH_MSGS
+ if (is_not_immed(msg) && (!self_on_heap || mp->data.attached)) {
+ Uint sz = size_object(msg);
+ mip[i].size = sz;
+ tot_heap_size += sz;
+ }
+#else
+ if (self_on_heap) {
+ if (mp->data.attached) {
+ ErtsMessage *tmp = NULL;
+ if (mp->data.attached != ERTS_MSG_COMBINED_HFRAG) {
+ erts_link_mbuf_to_proc(rp, mp->data.heap_frag);
+ mp->data.attached = NULL;
+ }
+ else {
+ /*
+ * Need to replace the message reference since
+ * we will get references to the message data
+ * from the heap...
+ */
+ ErtsMessage **mpp;
+ tmp = erts_alloc_message(0, NULL);
+ sys_memcpy((void *) tmp->m, (void *) mp->m,
+ sizeof(Eterm)*ERL_MESSAGE_REF_ARRAY_SZ);
+ mpp = i == 0 ? &rp->msg.first : &mip[i-1].msgp->next;
+ tmp->next = mp->next;
+ if (rp->msg.save == &mp->next)
+ rp->msg.save = &tmp->next;
+ if (rp->msg.last == &mp->next)
+ rp->msg.last = &tmp->next;
+ *mpp = tmp;
+ erts_save_message_in_proc(rp, mp);
+ mp = tmp;
+ }
+ }
+ }
+ else if (is_not_immed(msg)) {
+ Uint sz = size_object(msg);
+ mip[i].size = sz;
+ tot_heap_size += sz;
+ }
+
+#endif
+
+ mip[i].msgp = mp;
+ i++;
+ mp = mp->next;
+ }
+
+ return tot_heap_size;
}
void erts_factory_proc_init(ErtsHeapFactory* factory,
@@ -1127,53 +1439,147 @@ void erts_factory_proc_prealloc_init(ErtsHeapFactory* factory,
Process* p,
Sint size)
{
+ ErlHeapFragment *bp = p->mbuf;
factory->mode = FACTORY_HALLOC;
factory->p = p;
factory->hp_start = HAlloc(p, size);
factory->hp = factory->hp_start;
factory->hp_end = factory->hp_start + size;
factory->off_heap = &p->off_heap;
+ factory->message = NULL;
factory->off_heap_saved.first = p->off_heap.first;
factory->off_heap_saved.overhead = p->off_heap.overhead;
- factory->heap_frags_saved = p->mbuf;
+ factory->heap_frags_saved = bp;
+ factory->heap_frags_saved_used = bp ? bp->used_size : 0;
factory->heap_frags = NULL; /* not used */
factory->alloc_type = 0; /* not used */
}
-void erts_factory_message_init(ErtsHeapFactory* factory,
- Process* rp,
- Eterm* hp,
- ErlHeapFragment* bp)
+void erts_factory_heap_frag_init(ErtsHeapFactory* factory,
+ ErlHeapFragment* bp)
+{
+ factory->mode = FACTORY_HEAP_FRAGS;
+ factory->p = NULL;
+ factory->hp_start = bp->mem;
+ factory->hp = bp->mem;
+ factory->hp_end = bp->mem + bp->alloc_size;
+ factory->off_heap = &bp->off_heap;
+ factory->message = NULL;
+ factory->heap_frags = bp;
+ factory->heap_frags_saved = NULL;
+ factory->heap_frags_saved_used = 0;
+ factory->alloc_type = ERTS_ALC_T_HEAP_FRAG;
+ ASSERT(!bp->next);
+ factory->off_heap_saved.first = factory->off_heap->first;
+ factory->off_heap_saved.overhead = factory->off_heap->overhead;
+
+ ASSERT(factory->hp >= factory->hp_start && factory->hp <= factory->hp_end);
+}
+
+
+ErtsMessage *
+erts_factory_message_create(ErtsHeapFactory* factory,
+ Process *proc,
+ ErtsProcLocks *proc_locksp,
+ Uint sz)
+{
+ Eterm *hp;
+ ErlOffHeap *ohp;
+ ErtsMessage *msgp;
+ int on_heap;
+ erts_aint32_t state;
+
+ state = erts_smp_atomic32_read_nob(&proc->state);
+
+ if (state & ERTS_PSFLG_OFF_HEAP_MSGQ) {
+ msgp = erts_alloc_message(sz, &hp);
+ ohp = sz == 0 ? NULL : &msgp->hfrag.off_heap;
+ on_heap = 0;
+ }
+ else {
+ msgp = erts_try_alloc_message_on_heap(proc, &state,
+ proc_locksp,
+ sz, &hp, &ohp,
+ &on_heap);
+ }
+
+ if (on_heap) {
+ ASSERT(*proc_locksp & ERTS_PROC_LOCK_MAIN);
+ ASSERT(ohp == &proc->off_heap);
+ factory->mode = FACTORY_HALLOC;
+ factory->p = proc;
+ factory->heap_frags_saved = proc->mbuf;
+ factory->heap_frags_saved_used = proc->mbuf ? proc->mbuf->used_size : 0;
+ }
+ else {
+ factory->mode = FACTORY_MESSAGE;
+ factory->p = NULL;
+ factory->heap_frags_saved = NULL;
+ factory->heap_frags_saved_used = 0;
+
+ if (msgp->data.attached == ERTS_MSG_COMBINED_HFRAG) {
+ ASSERT(!msgp->hfrag.next);
+ factory->heap_frags = NULL;
+ }
+ else {
+ ASSERT(!msgp->data.heap_frag
+ || !msgp->data.heap_frag->next);
+ factory->heap_frags = msgp->data.heap_frag;
+ }
+ }
+ factory->hp_start = hp;
+ factory->hp = hp;
+ factory->hp_end = hp + sz;
+ factory->message = msgp;
+ factory->off_heap = ohp;
+ factory->alloc_type = ERTS_ALC_T_HEAP_FRAG;
+ if (ohp) {
+ factory->off_heap_saved.first = ohp->first;
+ factory->off_heap_saved.overhead = ohp->overhead;
+ }
+ else {
+ factory->off_heap_saved.first = NULL;
+ factory->off_heap_saved.overhead = 0;
+ }
+
+ ASSERT(factory->hp >= factory->hp_start && factory->hp <= factory->hp_end);
+
+ return msgp;
+}
+
+void erts_factory_selfcontained_message_init(ErtsHeapFactory* factory,
+ ErtsMessage *msgp,
+ Eterm *hp)
{
- if (bp) {
- factory->mode = FACTORY_HEAP_FRAGS;
- factory->p = NULL;
- factory->hp_start = bp->mem;
- factory->hp = hp ? hp : bp->mem;
- factory->hp_end = bp->mem + bp->alloc_size;
- factory->off_heap = &bp->off_heap;
- factory->heap_frags = bp;
- factory->heap_frags_saved = bp;
- factory->alloc_type = ERTS_ALC_T_HEAP_FRAG;
- ASSERT(!bp->next);
+ ErlHeapFragment* bp;
+ if (msgp->data.attached == ERTS_MSG_COMBINED_HFRAG) {
+ bp = &msgp->hfrag;
+ factory->heap_frags = NULL;
}
else {
- factory->mode = FACTORY_HALLOC;
- factory->p = rp;
- factory->hp_start = hp;
- factory->hp = hp;
- factory->hp_end = HEAP_TOP(rp);
- factory->off_heap = &rp->off_heap;
- factory->heap_frags_saved = rp->mbuf;
- factory->heap_frags = NULL; /* not used */
- factory->alloc_type = 0; /* not used */
+ bp = msgp->data.heap_frag;
+ factory->heap_frags = bp;
}
+ factory->mode = FACTORY_MESSAGE;
+ factory->p = NULL;
+ factory->hp_start = bp->mem;
+ factory->hp = hp;
+ factory->hp_end = bp->mem + bp->alloc_size;
+ factory->message = msgp;
+ factory->off_heap = &bp->off_heap;
+ factory->heap_frags_saved = NULL;
+ factory->heap_frags_saved_used = 0;
+ factory->alloc_type = ERTS_ALC_T_HEAP_FRAG;
+ ASSERT(!bp->next);
factory->off_heap_saved.first = factory->off_heap->first;
factory->off_heap_saved.overhead = factory->off_heap->overhead;
ASSERT(factory->hp >= factory->hp_start && factory->hp <= factory->hp_end);
}
+/* One static sized heap that must suffice.
+ No extra heap fragments will be allocated.
+*/
void erts_factory_static_init(ErtsHeapFactory* factory,
Eterm* hp,
Uint size,
@@ -1188,6 +1594,23 @@ void erts_factory_static_init(ErtsHeapFactory* factory,
factory->off_heap_saved.overhead = factory->off_heap->overhead;
}
+/* A temporary heap with default buffer allocated/freed by client.
+ * factory_close is same as factory_undo
+ */
+void erts_factory_tmp_init(ErtsHeapFactory* factory, Eterm* hp, Uint size,
+ Uint32 atype)
+{
+ factory->mode = FACTORY_TMP;
+ factory->hp_start = hp;
+ factory->hp = hp;
+ factory->hp_end = hp + size;
+ factory->heap_frags = NULL;
+ factory->off_heap_saved.first = NULL;
+ factory->off_heap_saved.overhead = 0;
+ factory->off_heap = &factory->off_heap_saved;
+ factory->alloc_type = atype;
+}
+
/* When we know the term is an immediate and need no heap.
*/
void erts_factory_dummy_init(ErtsHeapFactory* factory)
@@ -1230,8 +1653,17 @@ static void reserve_heap(ErtsHeapFactory* factory, Uint need, Uint xtra)
factory->hp_end = factory->hp + need;
return;
- case FACTORY_HEAP_FRAGS:
- bp = factory->heap_frags;
+ case FACTORY_MESSAGE:
+ if (!factory->heap_frags) {
+ ASSERT(factory->message->data.attached == ERTS_MSG_COMBINED_HFRAG);
+ bp = &factory->message->hfrag;
+ }
+ else {
+ /* Fall through */
+ case FACTORY_HEAP_FRAGS:
+ case FACTORY_TMP:
+ bp = factory->heap_frags;
+ }
if (bp) {
ASSERT(factory->hp > bp->mem);
@@ -1269,8 +1701,23 @@ void erts_factory_close(ErtsHeapFactory* factory)
HRelease(factory->p, factory->hp_end, factory->hp);
break;
- case FACTORY_HEAP_FRAGS:
- bp = factory->heap_frags;
+ case FACTORY_MESSAGE:
+ if (!factory->heap_frags) {
+ if (factory->message->data.attached == ERTS_MSG_COMBINED_HFRAG)
+ bp = &factory->message->hfrag;
+ else
+ bp = NULL;
+ }
+ else {
+ if (factory->message->data.attached == ERTS_MSG_COMBINED_HFRAG)
+ factory->message->hfrag.next = factory->heap_frags;
+ else
+ factory->message->data.heap_frag = factory->heap_frags;
+
+ /* Fall through */
+ case FACTORY_HEAP_FRAGS:
+ bp = factory->heap_frags;
+ }
if (bp) {
ASSERT(factory->hp >= bp->mem);
@@ -1280,6 +1727,9 @@ void erts_factory_close(ErtsHeapFactory* factory)
bp->used_size = factory->hp - bp->mem;
}
break;
+ case FACTORY_TMP:
+ erts_factory_undo(factory);
+ break;
case FACTORY_STATIC: break;
case FACTORY_CLOSED: break;
default:
@@ -1291,17 +1741,47 @@ void erts_factory_close(ErtsHeapFactory* factory)
void erts_factory_trim_and_close(ErtsHeapFactory* factory,
Eterm *brefs, Uint brefs_size)
{
- if (factory->mode == FACTORY_HEAP_FRAGS) {
- ErlHeapFragment* bp = factory->heap_frags;
+ ErlHeapFragment *bp;
+
+ switch (factory->mode) {
+ case FACTORY_MESSAGE: {
+ ErtsMessage *mp = factory->message;
+ if (mp->data.attached == ERTS_MSG_COMBINED_HFRAG) {
+ if (!mp->hfrag.next) {
+ Uint sz = factory->hp - factory->hp_start;
+ mp = erts_shrink_message(mp, sz, brefs, brefs_size);
+ factory->message = mp;
+ factory->mode = FACTORY_CLOSED;
+ return;
+ }
+ /*else we don't trim multi fragmented messages for now (off_heap...) */
+ break;
+ }
+ /* Fall through... */
+ }
+ case FACTORY_HEAP_FRAGS:
+ bp = factory->heap_frags;
+ if (!bp)
+ break;
if (bp->next == NULL) {
Uint used_sz = factory->hp - bp->mem;
ASSERT(used_sz <= bp->alloc_size);
- factory->heap_frags = erts_resize_message_buffer(bp, used_sz,
- brefs, brefs_size);
+ if (used_sz > 0)
+ bp = erts_resize_message_buffer(bp, used_sz,
+ brefs, brefs_size);
+ else {
+ free_message_buffer(bp);
+ bp = NULL;
+ }
+ factory->heap_frags = bp;
+ if (factory->mode == FACTORY_MESSAGE)
+ factory->message->data.heap_frag = bp;
factory->mode = FACTORY_CLOSED;
return;
}
- /*else we don't trim multi fragmented messages for now */
+ /*else we don't trim multi fragmented messages for now (off_heap...) */
+ default:
+ break;
}
erts_factory_close(factory);
}
@@ -1349,38 +1829,47 @@ void erts_factory_undo(ErtsHeapFactory* factory)
/* Rollback heap top
*/
- if (factory->heap_frags_saved == NULL) { /* No heap frags when we started */
- ASSERT(factory->hp_start >= HEAP_START(factory->p));
- ASSERT(factory->hp_start <= HEAP_LIMIT(factory->p));
- HEAP_TOP(factory->p) = factory->hp_start;
- }
- else {
+ if (HEAP_START(factory->p) <= factory->hp_start
+ && factory->hp_start <= HEAP_LIMIT(factory->p)) {
+ HEAP_TOP(factory->p) = factory->hp_start;
+ }
+
+ /* Fix last heap frag */
+ if (factory->heap_frags_saved) {
ASSERT(factory->heap_frags_saved == factory->p->mbuf);
- if (factory->hp_start == factory->heap_frags_saved->mem) {
+ if (factory->hp_start != factory->heap_frags_saved->mem)
+ factory->heap_frags_saved->used_size = factory->heap_frags_saved_used;
+ else {
factory->p->mbuf = factory->p->mbuf->next;
ERTS_HEAP_FREE(ERTS_ALC_T_HEAP_FRAG, factory->heap_frags_saved,
ERTS_HEAP_FRAG_SIZE(factory->heap_frags_saved->alloc_size));
}
- else if (factory->hp_start != factory->hp_end) {
- unsigned remains = factory->hp_start - factory->heap_frags_saved->mem;
- ASSERT(remains > 0 && remains < factory->heap_frags_saved->used_size);
- factory->heap_frags_saved->used_size = remains;
- }
}
}
break;
+ case FACTORY_MESSAGE:
+ if (factory->message->data.attached == ERTS_MSG_COMBINED_HFRAG)
+ factory->message->hfrag.next = factory->heap_frags;
+ else
+ factory->message->data.heap_frag = factory->heap_frags;
+ erts_cleanup_messages(factory->message);
+ break;
+ case FACTORY_TMP:
case FACTORY_HEAP_FRAGS:
+ erts_cleanup_offheap(factory->off_heap);
+ factory->off_heap->first = NULL;
+
bp = factory->heap_frags;
- do {
+ while (bp != NULL) {
ErlHeapFragment* next_bp = bp->next;
- erts_cleanup_offheap(&bp->off_heap);
+ ASSERT(bp->off_heap.first == NULL);
ERTS_HEAP_FREE(factory->alloc_type, (void *) bp,
- ERTS_HEAP_FRAG_SIZE(bp->size));
+ ERTS_HEAP_FRAG_SIZE(bp->alloc_size));
bp = next_bp;
- }while (bp != NULL);
+ }
break;
case FACTORY_CLOSED: break;
@@ -1394,4 +1883,3 @@ void erts_factory_undo(ErtsHeapFactory* factory)
factory->heap_frags = NULL;
#endif
}
-
diff --git a/erts/emulator/beam/erl_message.h b/erts/emulator/beam/erl_message.h
index f37b430d27..60035d15ae 100644
--- a/erts/emulator/beam/erl_message.h
+++ b/erts/emulator/beam/erl_message.h
@@ -24,6 +24,8 @@
struct proc_bin;
struct external_thing_;
+typedef struct erl_mesg ErtsMessage;
+
/*
* This struct represents data that must be updated by structure copy,
* but is stored outside of any heap.
@@ -54,15 +56,19 @@ typedef struct {
enum {
FACTORY_CLOSED = 0,
FACTORY_HALLOC,
+ FACTORY_MESSAGE,
FACTORY_HEAP_FRAGS,
- FACTORY_STATIC
+ FACTORY_STATIC,
+ FACTORY_TMP
} mode;
Process* p;
Eterm* hp_start;
Eterm* hp;
Eterm* hp_end;
+ ErtsMessage *message;
struct erl_heap_fragment* heap_frags;
struct erl_heap_fragment* heap_frags_saved;
+ Uint heap_frags_saved_used;
ErlOffHeap* off_heap;
ErlOffHeap off_heap_saved;
Uint32 alloc_type;
@@ -70,8 +76,12 @@ typedef struct {
void erts_factory_proc_init(ErtsHeapFactory*, Process*);
void erts_factory_proc_prealloc_init(ErtsHeapFactory*, Process*, Sint size);
-void erts_factory_message_init(ErtsHeapFactory*, Process*, Eterm* hp, struct erl_heap_fragment*);
+void erts_factory_heap_frag_init(ErtsHeapFactory*, struct erl_heap_fragment*);
+ErtsMessage *erts_factory_message_create(ErtsHeapFactory *, Process *,
+ ErtsProcLocks *, Uint sz);
+void erts_factory_selfcontained_message_init(ErtsHeapFactory*, ErtsMessage *, Eterm *);
void erts_factory_static_init(ErtsHeapFactory*, Eterm* hp, Uint size, ErlOffHeap*);
+void erts_factory_tmp_init(ErtsHeapFactory*, Eterm* hp, Uint size, Uint32 atype);
void erts_factory_dummy_init(ErtsHeapFactory*);
Eterm* erts_produce_heap(ErtsHeapFactory*, Uint need, Uint xtra);
@@ -91,6 +101,8 @@ void erts_factory_undo(ErtsHeapFactory*);
#include "external.h"
#include "erl_process.h"
+#define ERTS_INVALID_HFRAG_PTR ((ErlHeapFragment *) ~((UWord) 7))
+
/*
* This struct represents a heap fragment, which is used when there
* isn't sufficient room in the process heap and we can't do a GC.
@@ -105,33 +117,53 @@ struct erl_heap_fragment {
Eterm mem[1]; /* Data */
};
-typedef struct erl_mesg {
- struct erl_mesg* next; /* Next message */
- union {
- ErtsDistExternal *dist_ext;
- ErlHeapFragment *heap_frag;
- void *attached;
- } data;
+/* m[0] = message, m[1] = seq trace token */
+#define ERL_MESSAGE_REF_ARRAY_SZ 2
+#define ERL_MESSAGE_TERM(mp) ((mp)->m[0])
+#define ERL_MESSAGE_TOKEN(mp) ((mp)->m[1])
+
#ifdef USE_VM_PROBES
- Eterm m[3]; /* m[0] = message, m[1] = seq trace token, m[3] = dynamic trace user tag */
+/* m[2] = dynamic trace user tag */
+#undef ERL_MESSAGE_REF_ARRAY_SZ
+#define ERL_MESSAGE_REF_ARRAY_SZ 3
+#define ERL_MESSAGE_DT_UTAG(mp) ((mp)->m[2])
#else
- Eterm m[2]; /* m[0] = message, m[1] = seq trace token */
#endif
-} ErlMessage;
-#define ERL_MESSAGE_TERM(mp) ((mp)->m[0])
-#define ERL_MESSAGE_TOKEN(mp) ((mp)->m[1])
#ifdef USE_VM_PROBES
-#define ERL_MESSAGE_DT_UTAG(mp) ((mp)->m[2])
+#define have_no_seqtrace(T) ((T) == NIL || (T) == am_have_dt_utag)
+#else
+#define have_no_seqtrace(T) ((T) == NIL)
#endif
+#define have_seqtrace(T) (!have_no_seqtrace(T))
+
+#define ERL_MESSAGE_REF_FIELDS__ \
+ ErtsMessage *next; /* Next message */ \
+ union { \
+ ErtsDistExternal *dist_ext; \
+ ErlHeapFragment *heap_frag; \
+ void *attached; \
+ } data; \
+ Eterm m[ERL_MESSAGE_REF_ARRAY_SZ]
+
+
+typedef struct erl_msg_ref__ {
+ ERL_MESSAGE_REF_FIELDS__;
+} ErtsMessageRef;
+
+struct erl_mesg {
+ ERL_MESSAGE_REF_FIELDS__;
+
+ ErlHeapFragment hfrag;
+};
/* Size of default message buffer (erl_message.c) */
#define ERL_MESSAGE_BUF_SZ 500
typedef struct {
- ErlMessage* first;
- ErlMessage** last; /* point to the last next pointer */
- ErlMessage** save;
+ ErtsMessage* first;
+ ErtsMessage** last; /* point to the last next pointer */
+ ErtsMessage** save;
Sint len; /* queue length */
/*
@@ -139,14 +171,14 @@ typedef struct {
* recv_set/1 instructions.
*/
BeamInstr* mark; /* address to rec_loop/2 instruction */
- ErlMessage** saved_last; /* saved last pointer */
+ ErtsMessage** saved_last; /* saved last pointer */
} ErlMessageQueue;
#ifdef ERTS_SMP
typedef struct {
- ErlMessage* first;
- ErlMessage** last; /* point to the last next pointer */
+ ErtsMessage* first;
+ ErtsMessage** last; /* point to the last next pointer */
Sint len; /* queue length */
} ErlMessageInQueue;
@@ -197,7 +229,7 @@ do { \
/* Unlink current message */
#define UNLINK_MESSAGE(p,msgp) do { \
- ErlMessage* __mp = (msgp)->next; \
+ ErtsMessage* __mp = (msgp)->next; \
*(p)->msg.save = __mp; \
(p)->msg.len--; \
if (__mp == NULL) \
@@ -213,76 +245,33 @@ do { \
#define SAVE_MESSAGE(p) \
(p)->msg.save = &(*(p)->msg.save)->next
-/*
- * ErtsMoveMsgAttachmentIntoProc() moves data attached to a message
- * onto the heap of a process. The attached data is the content of
- * the the message either on the internal format or on the external
- * format, and also possibly a seq trace token on the internal format.
- * If the message content is on the external format, the decode might
- * fail. If the decoding fails, ERL_MESSAGE_TERM(M) will contain
- * THE_NON_VALUE. That is, ERL_MESSAGE_TERM(M) *has* to be checked
- * afterwards and taken care of appropriately.
- *
- * ErtsMoveMsgAttachmentIntoProc() will shallow copy to heap if
- * possible; otherwise, move to heap via garbage collection.
- *
- * ErtsMoveMsgAttachmentIntoProc() is used when receiveing messages
- * in process_main() and in hipe_check_get_msg().
- */
-
-#define ErtsMoveMsgAttachmentIntoProc(M, P, ST, HT, FC, SWPO, SWPI) \
-do { \
- if ((M)->data.attached) { \
- Uint need__ = erts_msg_attached_data_size((M)); \
- { SWPO ; } \
- if ((ST) - (HT) >= need__) { \
- ErtsHeapFactory factory__; \
- erts_factory_proc_prealloc_init(&factory__, (P), need__); \
- erts_move_msg_attached_data_to_heap(&factory__, (M)); \
- erts_factory_close(&factory__); \
- if ((P)->mbuf != NULL) { \
- /* Heap was exhausted by messages. This is a rare case */ \
- /* that can currently (OTP 18) only happen if hamts are */ \
- /* far exceeding the estimated heap size. Do GC. */ \
- (FC) -= erts_garbage_collect((P), 0, NULL, 0); \
- } \
- } \
- else { \
- (FC) -= erts_garbage_collect((P), 0, NULL, 0); \
- } \
- { SWPI ; } \
- ASSERT(!(M)->data.attached); \
- } \
-} while (0)
-
#define ERTS_SND_FLG_NO_SEQ_TRACE (((unsigned) 1) << 0)
#define ERTS_HEAP_FRAG_SIZE(DATA_WORDS) \
(sizeof(ErlHeapFragment) - sizeof(Eterm) + (DATA_WORDS)*sizeof(Eterm))
-#define ERTS_INIT_HEAP_FRAG(HEAP_FRAG_P, DATA_WORDS) \
-do { \
- (HEAP_FRAG_P)->next = NULL; \
- (HEAP_FRAG_P)->alloc_size = (DATA_WORDS); \
- (HEAP_FRAG_P)->used_size = (DATA_WORDS); \
- (HEAP_FRAG_P)->off_heap.first = NULL; \
- (HEAP_FRAG_P)->off_heap.overhead = 0; \
-} while (0)
+#define ERTS_INIT_HEAP_FRAG(HEAP_FRAG_P, USED_WORDS, DATA_WORDS) \
+ do { \
+ (HEAP_FRAG_P)->next = NULL; \
+ (HEAP_FRAG_P)->alloc_size = (DATA_WORDS); \
+ (HEAP_FRAG_P)->used_size = (USED_WORDS); \
+ (HEAP_FRAG_P)->off_heap.first = NULL; \
+ (HEAP_FRAG_P)->off_heap.overhead = 0; \
+ } while (0)
void init_message(void);
-void free_message(ErlMessage *);
ErlHeapFragment* new_message_buffer(Uint);
ErlHeapFragment* erts_resize_message_buffer(ErlHeapFragment *, Uint,
Eterm *, Uint);
void free_message_buffer(ErlHeapFragment *);
void erts_queue_dist_message(Process*, ErtsProcLocks*, ErtsDistExternal *, Eterm);
#ifdef USE_VM_PROBES
-void erts_queue_message_probe(Process*, ErtsProcLocks*, ErlHeapFragment*,
+void erts_queue_message_probe(Process*, ErtsProcLocks*, ErtsMessage*,
Eterm message, Eterm seq_trace_token, Eterm dt_utag);
#define erts_queue_message(RP,RL,BP,Msg,SEQ) \
erts_queue_message_probe((RP),(RL),(BP),(Msg),(SEQ),NIL)
#else
-void erts_queue_message(Process*, ErtsProcLocks*, ErlHeapFragment*,
+void erts_queue_message(Process*, ErtsProcLocks*, ErtsMessage*,
Eterm message, Eterm seq_trace_token);
#define erts_queue_message_probe(RP,RL,BP,Msg,SEQ,TAG) \
erts_queue_message((RP),(RL),(BP),(Msg),(SEQ))
@@ -291,20 +280,141 @@ void erts_deliver_exit_message(Eterm, Process*, ErtsProcLocks *, Eterm, Eterm);
Sint erts_send_message(Process*, Process*, ErtsProcLocks*, Eterm, unsigned);
void erts_link_mbuf_to_proc(Process *proc, ErlHeapFragment *bp);
-void erts_move_msg_mbuf_to_heap(Eterm**, ErlOffHeap*, ErlMessage *);
-
-Uint erts_msg_attached_data_size_aux(ErlMessage *msg);
-void erts_move_msg_attached_data_to_heap(ErtsHeapFactory*, ErlMessage *);
-Eterm erts_msg_distext2heap(Process *, ErtsProcLocks *, ErlHeapFragment **,
- Eterm *, ErtsDistExternal *);
+Uint erts_msg_attached_data_size_aux(ErtsMessage *msg);
void erts_cleanup_offheap(ErlOffHeap *offheap);
+void erts_save_message_in_proc(Process *p, ErtsMessage *msg);
+Sint erts_move_messages_off_heap(Process *c_p);
+Sint erts_complete_off_heap_message_queue_change(Process *c_p);
+Eterm erts_change_message_queue_management(Process *c_p, Eterm new_state);
+
+int erts_decode_dist_message(Process *, ErtsProcLocks, ErtsMessage *, int);
+
+void erts_cleanup_messages(ErtsMessage *mp);
+
+typedef struct {
+ Uint size;
+ ErtsMessage *msgp;
+} ErtsMessageInfo;
+Uint erts_prep_msgq_for_inspection(Process *c_p,
+ Process *rp,
+ ErtsProcLocks rp_locks,
+ ErtsMessageInfo *mip);
+void *erts_alloc_message_ref(void);
+void erts_free_message_ref(void *);
+
+#define ERTS_SMALL_FIX_MSG_SZ 10
+#define ERTS_MEDIUM_FIX_MSG_SZ 20
+#define ERTS_LARGE_FIX_MSG_SZ 30
+
+void *erts_alloc_small_message(void);
+void erts_free_small_message(void *mp);
+
+typedef struct {
+ ErtsMessage m;
+ Eterm data[ERTS_SMALL_FIX_MSG_SZ-1];
+} ErtsSmallFixSzMessage;
+
+typedef struct {
+ ErtsMessage m;
+ Eterm data[ERTS_MEDIUM_FIX_MSG_SZ-1];
+} ErtsMediumFixSzMessage;
+
+typedef struct {
+ ErtsMessage m;
+ Eterm data[ERTS_LARGE_FIX_MSG_SZ-1];
+} ErtsLargeFixSzMessage;
+
+ErtsMessage *erts_try_alloc_message_on_heap(Process *pp,
+ erts_aint32_t *psp,
+ ErtsProcLocks *plp,
+ Uint sz,
+ Eterm **hpp,
+ ErlOffHeap **ohpp,
+ int *on_heap_p);
+ErtsMessage *erts_realloc_shrink_message(ErtsMessage *mp, Uint sz,
+ Eterm *brefs, Uint brefs_size);
+
+ERTS_GLB_FORCE_INLINE ErtsMessage *erts_alloc_message(Uint sz, Eterm **hpp);
+ERTS_GLB_FORCE_INLINE ErtsMessage *erts_shrink_message(ErtsMessage *mp, Uint sz,
+ Eterm *brefs, Uint brefs_size);
+ERTS_GLB_FORCE_INLINE void erts_free_message(ErtsMessage *mp);
ERTS_GLB_INLINE Uint erts_used_frag_sz(const ErlHeapFragment*);
-ERTS_GLB_INLINE Uint erts_msg_attached_data_size(ErlMessage *msg);
+ERTS_GLB_INLINE Uint erts_msg_attached_data_size(ErtsMessage *msg);
+
+#define ERTS_MSG_COMBINED_HFRAG ((void *) 0x1)
#if ERTS_GLB_INLINE_INCL_FUNC_DEF
+
+ERTS_GLB_FORCE_INLINE ErtsMessage *erts_alloc_message(Uint sz, Eterm **hpp)
+{
+ ErtsMessage *mp;
+
+ if (sz == 0) {
+ mp = erts_alloc_message_ref();
+ mp->next = NULL;
+ ERL_MESSAGE_TERM(mp) = NIL;
+ mp->data.attached = NULL;
+ if (hpp)
+ *hpp = NULL;
+ return mp;
+ }
+
+ mp = erts_alloc(ERTS_ALC_T_MSG,
+ sizeof(ErtsMessage) + (sz - 1)*sizeof(Eterm));
+
+ mp->next = NULL;
+ ERL_MESSAGE_TERM(mp) = NIL;
+ mp->data.attached = ERTS_MSG_COMBINED_HFRAG;
+ ERTS_INIT_HEAP_FRAG(&mp->hfrag, sz, sz);
+
+ if (hpp)
+ *hpp = &mp->hfrag.mem[0];
+
+ return mp;
+}
+
+ERTS_GLB_FORCE_INLINE ErtsMessage *
+erts_shrink_message(ErtsMessage *mp, Uint sz, Eterm *brefs, Uint brefs_size)
+{
+ if (sz == 0) {
+ ErtsMessage *nmp;
+ if (!mp->data.attached)
+ return mp;
+ ASSERT(mp->data.attached == ERTS_MSG_COMBINED_HFRAG);
+ nmp = erts_alloc_message_ref();
+#ifdef DEBUG
+ if (brefs && brefs_size) {
+ int i;
+ for (i = 0; i < brefs_size; i++)
+ ASSERT(is_non_value(brefs[i]) || is_immed(brefs[i]));
+ }
+#endif
+ erts_free(ERTS_ALC_T_MSG, mp);
+ return nmp;
+ }
+
+ ASSERT(mp->data.attached == ERTS_MSG_COMBINED_HFRAG);
+ ASSERT(mp->hfrag.used_size >= sz);
+
+ if (sz >= (mp->hfrag.alloc_size - mp->hfrag.alloc_size / 16)) {
+ mp->hfrag.used_size = sz;
+ return mp;
+ }
+
+ return erts_realloc_shrink_message(mp, sz, brefs, brefs_size);
+}
+
+ERTS_GLB_FORCE_INLINE void erts_free_message(ErtsMessage *mp)
+{
+ if (mp->data.attached != ERTS_MSG_COMBINED_HFRAG)
+ erts_free_message_ref(mp);
+ else
+ erts_free(ERTS_ALC_T_MSG, mp);
+}
+
ERTS_GLB_INLINE Uint erts_used_frag_sz(const ErlHeapFragment* bp)
{
Uint sz = 0;
@@ -314,11 +424,17 @@ ERTS_GLB_INLINE Uint erts_used_frag_sz(const ErlHeapFragment* bp)
return sz;
}
-ERTS_GLB_INLINE Uint erts_msg_attached_data_size(ErlMessage *msg)
+ERTS_GLB_INLINE Uint erts_msg_attached_data_size(ErtsMessage *msg)
{
ASSERT(msg->data.attached);
- if (is_value(ERL_MESSAGE_TERM(msg)))
- return erts_used_frag_sz(msg->data.heap_frag);
+ if (is_value(ERL_MESSAGE_TERM(msg))) {
+ ErlHeapFragment *bp;
+ if (msg->data.attached == ERTS_MSG_COMBINED_HFRAG)
+ bp = &msg->hfrag;
+ else
+ bp = msg->data.heap_frag;
+ return erts_used_frag_sz(bp);
+ }
else if (msg->data.dist_ext->heap_size < 0)
return erts_msg_attached_data_size_aux(msg);
else {
diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c
index add4a66f90..d659788f30 100644
--- a/erts/emulator/beam/erl_nif.c
+++ b/erts/emulator/beam/erl_nif.c
@@ -314,6 +314,7 @@ int enif_send(ErlNifEnv* env, const ErlNifPid* to_pid,
ErtsProcLocks rp_locks = 0;
Process* rp;
Process* c_p;
+ ErtsMessage *mp;
ErlHeapFragment* frags;
Eterm receiver = to_pid->pid;
int flush_me = 0;
@@ -347,7 +348,7 @@ int enif_send(ErlNifEnv* env, const ErlNifPid* to_pid,
ASSERT(frags == MBUF(&menv->phony_proc));
if (frags != NULL) {
/* Move all offheap's from phony proc to the first fragment.
- Quick and dirty, but erts_move_msg_mbuf_to_heap doesn't care. */
+ Quick and dirty... */
ASSERT(!is_offheap(&frags->off_heap));
frags->off_heap = MSO(&menv->phony_proc);
clear_offheap(&MSO(&menv->phony_proc));
@@ -359,7 +360,9 @@ int enif_send(ErlNifEnv* env, const ErlNifPid* to_pid,
if (flush_me) {
flush_env(env); /* Needed for ERTS_HOLE_CHECK */
}
- erts_queue_message(rp, &rp_locks, frags, msg, am_undefined);
+ mp = erts_alloc_message(0, NULL);
+ mp->data.heap_frag = frags;
+ erts_queue_message(rp, &rp_locks, mp, msg, am_undefined);
if (c_p == rp)
rp_locks &= ~ERTS_PROC_LOCK_MAIN;
if (rp_locks)
@@ -376,9 +379,19 @@ ERL_NIF_TERM enif_make_copy(ErlNifEnv* dst_env, ERL_NIF_TERM src_term)
{
Uint sz;
Eterm* hp;
+#ifdef SHCOPY
+ erts_shcopy_t info;
+ INITIALIZE_SHCOPY(info);
+ sz = copy_shared_calculate(src_term, &info);
+ hp = alloc_heap(dst_env, sz);
+ src_term = copy_shared_perform(src_term, sz, &info, &hp, &MSO(dst_env->proc));
+ DESTROY_SHCOPY(info);
+ return src_term;
+#else
sz = size_object(src_term);
hp = alloc_heap(dst_env, sz);
return copy_struct(src_term, sz, &hp, &MSO(dst_env->proc));
+#endif
}
@@ -1173,6 +1186,7 @@ ErlNifTid enif_thread_self(void) { return erl_drv_thread_self(); }
int enif_equal_tids(ErlNifTid tid1, ErlNifTid tid2) { return erl_drv_equal_tids(tid1,tid2); }
void enif_thread_exit(void *resp) { erl_drv_thread_exit(resp); }
int enif_thread_join(ErlNifTid tid, void **respp) { return erl_drv_thread_join(tid,respp); }
+int enif_getenv(const char *key, char *value, size_t *value_size) { return erl_drv_getenv(key, value, value_size); }
int enif_fprintf(void* filep, const char* format, ...)
{
@@ -2230,17 +2244,17 @@ int enif_map_iterator_get_pair(ErlNifEnv *env,
***************************************************************************/
-static BeamInstr** get_func_pp(BeamInstr* mod_code, Eterm f_atom, unsigned arity)
+static BeamInstr** get_func_pp(BeamCodeHeader* mod_code, Eterm f_atom, unsigned arity)
{
- int n = (int) mod_code[MI_NUM_FUNCTIONS];
+ int n = (int) mod_code->num_functions;
int j;
for (j = 0; j < n; ++j) {
- BeamInstr* code_ptr = (BeamInstr*) mod_code[MI_FUNCTIONS+j];
+ BeamInstr* code_ptr = (BeamInstr*) mod_code->functions[j];
ASSERT(code_ptr[0] == (BeamInstr) BeamOp(op_i_func_info_IaaI));
if (f_atom == ((Eterm) code_ptr[3])
&& arity == ((unsigned) code_ptr[4])) {
- return (BeamInstr**) &mod_code[MI_FUNCTIONS+j];
+ return (BeamInstr**) &mod_code->functions[j];
}
}
return NULL;
@@ -2423,8 +2437,8 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2)
if (init_func != NULL)
handle = init_func;
- if (!in_area(caller, mod->curr.code, mod->curr.code_length)) {
- ASSERT(in_area(caller, mod->old.code, mod->old.code_length));
+ if (!in_area(caller, mod->curr.code_hdr, mod->curr.code_length)) {
+ ASSERT(in_area(caller, mod->old.code_hdr, mod->old.code_length));
ret = load_nif_error(BIF_P, "old_code", "Calling load_nif from old "
"module '%T' not allowed", mod_atom);
@@ -2478,7 +2492,7 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2)
for (i=0; i < entry->num_of_funcs && ret==am_ok; i++) {
BeamInstr** code_pp;
if (!erts_atom_get(f->name, sys_strlen(f->name), &f_atom, ERTS_ATOM_ENC_LATIN1)
- || (code_pp = get_func_pp(mod->curr.code, f_atom, f->arity))==NULL) {
+ || (code_pp = get_func_pp(mod->curr.code_hdr, f_atom, f->arity))==NULL) {
ret = load_nif_error(BIF_P,bad_lib,"Function not found %T:%s/%u",
mod_atom, f->name, f->arity);
}
@@ -2621,7 +2635,7 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2)
{
BeamInstr* code_ptr;
erts_atom_get(f->name, sys_strlen(f->name), &f_atom, ERTS_ATOM_ENC_LATIN1);
- code_ptr = *get_func_pp(mod->curr.code, f_atom, f->arity);
+ code_ptr = *get_func_pp(mod->curr.code_hdr, f_atom, f->arity);
if (code_ptr[1] == 0) {
code_ptr[5+0] = (BeamInstr) BeamOp(op_call_nif);
diff --git a/erts/emulator/beam/erl_nif.h b/erts/emulator/beam/erl_nif.h
index 5da6bb877a..1a21048ec9 100644
--- a/erts/emulator/beam/erl_nif.h
+++ b/erts/emulator/beam/erl_nif.h
@@ -48,9 +48,10 @@
** add ErlNifEntry options
** add ErlNifFunc flags
** 2.8: 18.0 add enif_has_pending_exception
+** 2.9: 18.2 enif_getenv
*/
#define ERL_NIF_MAJOR_VERSION 2
-#define ERL_NIF_MINOR_VERSION 8
+#define ERL_NIF_MINOR_VERSION 9
/*
* The emulator will refuse to load a nif-lib with a major version
@@ -222,6 +223,7 @@ typedef enum {
# define ERL_NIF_API_FUNC_DECL(RET_TYPE, NAME, ARGS) RET_TYPE (*NAME) ARGS
typedef struct {
# include "erl_nif_api_funcs.h"
+ void* erts_alc_test;
} TWinDynNifCallbacks;
extern TWinDynNifCallbacks WinDynNifCallbacks;
# undef ERL_NIF_API_FUNC_DECL
diff --git a/erts/emulator/beam/erl_nif_api_funcs.h b/erts/emulator/beam/erl_nif_api_funcs.h
index 2f2180e1aa..08b9afc6af 100644
--- a/erts/emulator/beam/erl_nif_api_funcs.h
+++ b/erts/emulator/beam/erl_nif_api_funcs.h
@@ -159,6 +159,7 @@ ERL_NIF_API_FUNC_DECL(int, enif_map_iterator_get_pair, (ErlNifEnv *env, ErlNifMa
ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_schedule_nif,(ErlNifEnv*,const char*,int,ERL_NIF_TERM (*)(ErlNifEnv*,int,const ERL_NIF_TERM[]),int,const ERL_NIF_TERM[]));
ERL_NIF_API_FUNC_DECL(int, enif_has_pending_exception, (ErlNifEnv *env, ERL_NIF_TERM* reason));
ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM, enif_raise_exception, (ErlNifEnv *env, ERL_NIF_TERM reason));
+ERL_NIF_API_FUNC_DECL(int,enif_getenv,(const char* key, char* value, size_t* value_size));
/*
** ADD NEW ENTRIES HERE (before this comment) !!!
@@ -310,6 +311,7 @@ ERL_NIF_API_FUNC_DECL(int,enif_is_on_dirty_scheduler,(ErlNifEnv*));
# define enif_schedule_nif ERL_NIF_API_FUNC_MACRO(enif_schedule_nif)
# define enif_has_pending_exception ERL_NIF_API_FUNC_MACRO(enif_has_pending_exception)
# define enif_raise_exception ERL_NIF_API_FUNC_MACRO(enif_raise_exception)
+# define enif_getenv ERL_NIF_API_FUNC_MACRO(enif_getenv)
/*
** ADD NEW ENTRIES HERE (before this comment)
diff --git a/erts/emulator/beam/erl_node_tables.c b/erts/emulator/beam/erl_node_tables.c
index e5bd0d58f0..13f14adbab 100644
--- a/erts/emulator/beam/erl_node_tables.c
+++ b/erts/emulator/beam/erl_node_tables.c
@@ -37,18 +37,18 @@ erts_smp_rwmtx_t erts_node_table_rwmtx;
DistEntry *erts_hidden_dist_entries;
DistEntry *erts_visible_dist_entries;
-DistEntry *erts_not_connected_dist_entries;
+DistEntry *erts_not_connected_dist_entries; /* including erts_this_dist_entry */
Sint erts_no_of_hidden_dist_entries;
Sint erts_no_of_visible_dist_entries;
-Sint erts_no_of_not_connected_dist_entries;
+Sint erts_no_of_not_connected_dist_entries; /* including erts_this_dist_entry */
DistEntry *erts_this_dist_entry;
ErlNode *erts_this_node;
char erts_this_node_sysname_BUFFER[256],
*erts_this_node_sysname = "uninitialized yet";
-static Uint node_entries;
-static Uint dist_entries;
+static Uint node_entries = 0;
+static Uint dist_entries = 0;
static int references_atoms_need_init = 1;
@@ -91,9 +91,6 @@ dist_table_alloc(void *dep_tmpl)
erts_smp_rwmtx_opt_t rwmtx_opt = ERTS_SMP_RWMTX_OPT_DEFAULT_INITER;
rwmtx_opt.type = ERTS_SMP_RWMTX_TYPE_FREQUENT_READ;
- if(((DistEntry *) dep_tmpl) == erts_this_dist_entry)
- return dep_tmpl;
-
sysname = ((DistEntry *) dep_tmpl)->sysname;
chnl_nr = make_small((Uint) atom_val(sysname));
dep = (DistEntry *) erts_alloc(ERTS_ALC_T_DIST_ENTRY, sizeof(DistEntry));
@@ -132,7 +129,9 @@ dist_table_alloc(void *dep_tmpl)
/* Link in */
- /* All new dist entries are "not connected" */
+ /* All new dist entries are "not connected".
+ * erts_this_dist_entry is also always included among "not connected"
+ */
dep->next = erts_not_connected_dist_entries;
if(erts_not_connected_dist_entries) {
ASSERT(erts_not_connected_dist_entries->prev == NULL);
@@ -149,9 +148,6 @@ dist_table_free(void *vdep)
{
DistEntry *dep = (DistEntry *) vdep;
- if(dep == erts_this_dist_entry)
- return;
-
ASSERT(is_nil(dep->cid));
ASSERT(dep->nlinks == NULL);
ASSERT(dep->node_links == NULL);
@@ -186,7 +182,7 @@ dist_table_free(void *vdep)
#endif
erts_free(ERTS_ALC_T_DIST_ENTRY, (void *) dep);
- ASSERT(dist_entries > 1);
+ ASSERT(dist_entries > 0);
dist_entries--;
}
@@ -306,7 +302,7 @@ static void try_delete_dist_entry(void *vdep)
* thread incremented refc twice. Once for the new reference
* and once for this thread.
*
- * If refc reach -1, noone has used the entry since we
+ * If refc reach -1, no one has used the entry since we
* set up the timer. Delete the entry.
*
* If refc reach 0, the entry is currently not in use
@@ -369,8 +365,7 @@ erts_dist_table_size(void)
ASSERT(dist_entries == (erts_no_of_visible_dist_entries
+ erts_no_of_hidden_dist_entries
- + erts_no_of_not_connected_dist_entries
- + 1 /* erts_this_dist_entry */));
+ + erts_no_of_not_connected_dist_entries));
#endif
res = (hash_table_sz(&erts_dist_table)
@@ -543,9 +538,6 @@ node_table_alloc(void *venp_tmpl)
{
ErlNode *enp;
- if(((ErlNode *) venp_tmpl) == erts_this_node)
- return venp_tmpl;
-
enp = (ErlNode *) erts_alloc(ERTS_ALC_T_NODE_ENTRY, sizeof(ErlNode));
node_entries++;
@@ -563,8 +555,7 @@ node_table_free(void *venp)
{
ErlNode *enp = (ErlNode *) venp;
- if(enp == erts_this_node)
- return;
+ ERTS_SMP_LC_ASSERT(enp != erts_this_node || erts_thr_progress_is_blocking());
erts_deref_dist_entry(enp->dist_entry);
#ifdef DEBUG
@@ -572,7 +563,7 @@ node_table_free(void *venp)
#endif
erts_free(ERTS_ALC_T_NODE_ENTRY, venp);
- ASSERT(node_entries > 1);
+ ASSERT(node_entries > 0);
node_entries--;
}
@@ -650,7 +641,7 @@ static void try_delete_node(void *venp)
* thread incremented refc twice. Once for the new reference
* and once for this thread.
*
- * If refc reach -1, noone has used the entry since we
+ * If refc reach -1, no one has used the entry since we
* set up the timer. Delete the entry.
*
* If refc reach 0, the entry is currently not in use
@@ -747,25 +738,24 @@ void erts_print_node_info(int to,
void
erts_set_this_node(Eterm sysname, Uint creation)
{
- erts_smp_rwmtx_rwlock(&erts_node_table_rwmtx);
- erts_smp_rwmtx_rwlock(&erts_dist_table_rwmtx);
+ ERTS_SMP_LC_ASSERT(erts_thr_progress_is_blocking());
+ ASSERT(erts_refc_read(&erts_this_dist_entry->refc, 2));
- (void) hash_erase(&erts_dist_table, (void *) erts_this_dist_entry);
- erts_this_dist_entry->sysname = sysname;
- erts_this_dist_entry->creation = creation;
- (void) hash_put(&erts_dist_table, (void *) erts_this_dist_entry);
+ if (erts_refc_dectest(&erts_this_node->refc, 0) == 0)
+ try_delete_node(erts_this_node);
- (void) hash_erase(&erts_node_table, (void *) erts_this_node);
- erts_this_node->sysname = sysname;
- erts_this_node->creation = creation;
- erts_this_node_sysname = erts_this_node_sysname_BUFFER;
- erts_snprintf(erts_this_node_sysname, sizeof(erts_this_node_sysname_BUFFER),
- "%T", sysname);
- (void) hash_put(&erts_node_table, (void *) erts_this_node);
+ if (erts_refc_dectest(&erts_this_dist_entry->refc, 0) == 0)
+ try_delete_dist_entry(erts_this_dist_entry);
- erts_smp_rwmtx_rwunlock(&erts_dist_table_rwmtx);
- erts_smp_rwmtx_rwunlock(&erts_node_table_rwmtx);
+ erts_this_node = NULL; /* to make sure refc is bumped for this node */
+ erts_this_node = erts_find_or_insert_node(sysname, creation);
+ erts_this_dist_entry = erts_this_node->dist_entry;
+
+ erts_refc_inc(&erts_this_dist_entry->refc, 2);
+ erts_this_node_sysname = erts_this_node_sysname_BUFFER;
+ erts_snprintf(erts_this_node_sysname, sizeof(erts_this_node_sysname_BUFFER),
+ "%T", sysname);
}
Uint
@@ -782,6 +772,7 @@ void erts_init_node_tables(int dd_sec)
{
erts_smp_rwmtx_opt_t rwmtx_opt = ERTS_SMP_RWMTX_OPT_DEFAULT_INITER;
HashFunctions f;
+ ErlNode node_tmpl;
if (dd_sec == ERTS_NODE_TAB_DELAY_GC_INFINITY)
node_tab_delete_delay = (ErtsMonotonicTime) -1;
@@ -793,6 +784,9 @@ void erts_init_node_tables(int dd_sec)
rwmtx_opt.type = ERTS_SMP_RWMTX_TYPE_FREQUENT_READ;
rwmtx_opt.lived = ERTS_SMP_RWMTX_LONG_LIVED;
+ erts_smp_rwmtx_init_opt(&erts_node_table_rwmtx, &rwmtx_opt, "node_table");
+ erts_smp_rwmtx_init_opt(&erts_dist_table_rwmtx, &rwmtx_opt, "dist_table");
+
f.hash = (H_FUN) dist_table_hash;
f.cmp = (HCMP_FUN) dist_table_cmp;
f.alloc = (HALLOC_FUN) dist_table_alloc;
@@ -800,13 +794,14 @@ void erts_init_node_tables(int dd_sec)
f.meta_alloc = (HMALLOC_FUN) erts_alloc;
f.meta_free = (HMFREE_FUN) erts_free;
f.meta_print = (HMPRINT_FUN) erts_print;
-
-
- erts_this_dist_entry = erts_alloc(ERTS_ALC_T_DIST_ENTRY, sizeof(DistEntry));
- dist_entries = 1;
-
hash_init(ERTS_ALC_T_DIST_TABLE, &erts_dist_table, "dist_table", 11, f);
+ f.hash = (H_FUN) node_table_hash;
+ f.cmp = (HCMP_FUN) node_table_cmp;
+ f.alloc = (HALLOC_FUN) node_table_alloc;
+ f.free = (HFREE_FUN) node_table_free;
+ hash_init(ERTS_ALC_T_NODE_TABLE, &erts_node_table, "node_table", 11, f);
+
erts_hidden_dist_entries = NULL;
erts_visible_dist_entries = NULL;
erts_not_connected_dist_entries = NULL;
@@ -814,69 +809,23 @@ void erts_init_node_tables(int dd_sec)
erts_no_of_visible_dist_entries = 0;
erts_no_of_not_connected_dist_entries = 0;
- erts_this_dist_entry->next = NULL;
- erts_this_dist_entry->prev = NULL;
- erts_refc_init(&erts_this_dist_entry->refc, 1); /* erts_this_node */
-
- erts_smp_rwmtx_init_opt_x(&erts_this_dist_entry->rwmtx,
- &rwmtx_opt,
- "dist_entry",
- make_small(ERST_INTERNAL_CHANNEL_NO));
- erts_this_dist_entry->sysname = am_Noname;
- erts_this_dist_entry->cid = NIL;
- erts_this_dist_entry->connection_id = 0;
- erts_this_dist_entry->status = 0;
- erts_this_dist_entry->flags = 0;
- erts_this_dist_entry->version = 0;
-
- erts_smp_mtx_init_x(&erts_this_dist_entry->lnk_mtx,
- "dist_entry_links",
- make_small(ERST_INTERNAL_CHANNEL_NO));
- erts_this_dist_entry->node_links = NULL;
- erts_this_dist_entry->nlinks = NULL;
- erts_this_dist_entry->monitors = NULL;
-
- erts_smp_mtx_init_x(&erts_this_dist_entry->qlock,
- "dist_entry_out_queue",
- make_small(ERST_INTERNAL_CHANNEL_NO));
- erts_this_dist_entry->qflgs = 0;
- erts_this_dist_entry->qsize = 0;
- erts_this_dist_entry->out_queue.first = NULL;
- erts_this_dist_entry->out_queue.last = NULL;
- erts_this_dist_entry->suspended = NULL;
-
- erts_this_dist_entry->finalized_out_queue.first = NULL;
- erts_this_dist_entry->finalized_out_queue.last = NULL;
- erts_smp_atomic_init_nob(&erts_this_dist_entry->dist_cmd_scheduled, 0);
- erts_port_task_handle_init(&erts_this_dist_entry->dist_cmd);
- erts_this_dist_entry->send = NULL;
- erts_this_dist_entry->cache = NULL;
-
- (void) hash_put(&erts_dist_table, (void *) erts_this_dist_entry);
+ node_tmpl.sysname = am_Noname;
+ node_tmpl.creation = 0;
+ erts_this_node = hash_put(&erts_node_table, &node_tmpl);
+ /* +1 for erts_this_node */
+ erts_refc_init(&erts_this_node->refc, 1);
- f.hash = (H_FUN) node_table_hash;
- f.cmp = (HCMP_FUN) node_table_cmp;
- f.alloc = (HALLOC_FUN) node_table_alloc;
- f.free = (HFREE_FUN) node_table_free;
-
- hash_init(ERTS_ALC_T_NODE_TABLE, &erts_node_table, "node_table", 11, f);
+ ASSERT(erts_this_node->dist_entry != NULL);
+ erts_this_dist_entry = erts_this_node->dist_entry;
+ /* +1 for erts_this_dist_entry */
+ /* +1 for erts_this_node->dist_entry */
+ erts_refc_init(&erts_this_dist_entry->refc, 2);
- erts_this_node = erts_alloc(ERTS_ALC_T_NODE_ENTRY, sizeof(ErlNode));
- node_entries = 1;
- erts_refc_init(&erts_this_node->refc, 1); /* The system itself */
- erts_this_node->sysname = am_Noname;
- erts_this_node->creation = 0;
- erts_this_node->dist_entry = erts_this_dist_entry;
erts_this_node_sysname = erts_this_node_sysname_BUFFER;
erts_snprintf(erts_this_node_sysname, sizeof(erts_this_node_sysname_BUFFER),
"%T", erts_this_node->sysname);
- (void) hash_put(&erts_node_table, (void *) erts_this_node);
-
- erts_smp_rwmtx_init_opt(&erts_node_table_rwmtx, &rwmtx_opt, "node_table");
- erts_smp_rwmtx_init_opt(&erts_dist_table_rwmtx, &rwmtx_opt, "dist_table");
-
references_atoms_need_init = 1;
}
@@ -1398,6 +1347,10 @@ setup_reference_table(void)
SYSTEM_REF,
TUPLE2(&heap[0], AM_system, am_undefined));
+ insert_dist_entry(erts_this_dist_entry,
+ SYSTEM_REF,
+ TUPLE2(&heap[0], AM_system, am_undefined),
+ erts_this_node->creation);
UnUseTmpHeapNoproc(3);
max = erts_ptab_max(&erts_proc);
@@ -1405,67 +1358,55 @@ setup_reference_table(void)
for (i = 0; i < max; i++) {
Process *proc = erts_pix2proc(i);
if (proc) {
- ErlMessage *msg;
+ int mli;
+ ErtsMessage *msg_list[] = {
+ proc->msg.first,
+#ifdef ERTS_SMP
+ proc->msg_inq.first,
+#endif
+ proc->msg_frag};
/* Insert Heap */
insert_offheap(&(proc->off_heap),
HEAP_REF,
proc->common.id);
- /* Insert message buffers */
+ /* Insert heap fragments buffers */
for(hfp = proc->mbuf; hfp; hfp = hfp->next)
insert_offheap(&(hfp->off_heap),
HEAP_REF,
proc->common.id);
- /* Insert msg msg buffers */
- for (msg = proc->msg.first; msg; msg = msg->next) {
- ErlHeapFragment *heap_frag = NULL;
- if (msg->data.attached) {
- if (is_value(ERL_MESSAGE_TERM(msg)))
- heap_frag = msg->data.heap_frag;
- else {
- if (msg->data.dist_ext->dep)
- insert_dist_entry(msg->data.dist_ext->dep,
- HEAP_REF, proc->common.id, 0);
- if (is_not_nil(ERL_MESSAGE_TOKEN(msg)))
- heap_frag = erts_dist_ext_trailer(msg->data.dist_ext);
+
+ /* Insert msg buffers */
+ for (mli = 0; mli < sizeof(msg_list)/sizeof(msg_list[0]); mli++) {
+ ErtsMessage *msg;
+ for (msg = msg_list[mli]; msg; msg = msg->next) {
+ ErlHeapFragment *heap_frag = NULL;
+ if (msg->data.attached) {
+ if (msg->data.attached == ERTS_MSG_COMBINED_HFRAG)
+ heap_frag = &msg->hfrag;
+ else if (is_value(ERL_MESSAGE_TERM(msg)))
+ heap_frag = msg->data.heap_frag;
+ else {
+ if (msg->data.dist_ext->dep)
+ insert_dist_entry(msg->data.dist_ext->dep,
+ HEAP_REF, proc->common.id, 0);
+ if (is_not_nil(ERL_MESSAGE_TOKEN(msg)))
+ heap_frag = erts_dist_ext_trailer(msg->data.dist_ext);
+ }
}
- }
- if (heap_frag)
- insert_offheap(&(heap_frag->off_heap),
- HEAP_REF,
- proc->common.id);
- }
-#ifdef ERTS_SMP
- for (msg = proc->msg_inq.first; msg; msg = msg->next) {
- ErlHeapFragment *heap_frag = NULL;
- if (msg->data.attached) {
- if (is_value(ERL_MESSAGE_TERM(msg)))
- heap_frag = msg->data.heap_frag;
- else {
- if (msg->data.dist_ext->dep)
- insert_dist_entry(msg->data.dist_ext->dep,
- HEAP_REF, proc->common.id, 0);
- if (is_not_nil(ERL_MESSAGE_TOKEN(msg)))
- heap_frag = erts_dist_ext_trailer(msg->data.dist_ext);
+ while (heap_frag) {
+ insert_offheap(&(heap_frag->off_heap),
+ HEAP_REF,
+ proc->common.id);
+ heap_frag = heap_frag->next;
}
}
- if (heap_frag)
- insert_offheap(&(heap_frag->off_heap),
- HEAP_REF,
- proc->common.id);
}
-#endif
/* Insert links */
if (ERTS_P_LINKS(proc))
insert_links(ERTS_P_LINKS(proc), proc->common.id);
if (ERTS_P_MONITORS(proc))
insert_monitors(ERTS_P_MONITORS(proc), proc->common.id);
- /* Insert controller */
- {
- DistEntry *dep = ERTS_PROC_GET_DIST_ENTRY(proc);
- if (dep)
- insert_dist_entry(dep, CTRL_REF, proc->common.id, 0);
- }
}
}
diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c
index 03cb3dc254..2c62685f8c 100644
--- a/erts/emulator/beam/erl_process.c
+++ b/erts/emulator/beam/erl_process.c
@@ -148,6 +148,7 @@ extern BeamInstr beam_apply[];
extern BeamInstr beam_exit[];
extern BeamInstr beam_continue_exit[];
+int erts_default_spo_flags = 0;
int erts_eager_check_io = 1;
int erts_sched_compact_load;
int erts_sched_balance_util = 0;
@@ -334,7 +335,6 @@ static ErtsAlignedSchedulerSleepInfo *aligned_dirty_io_sched_sleep_info;
static Uint last_reductions;
static Uint last_exact_reductions;
-Uint erts_default_process_flags;
Eterm erts_system_monitor;
Eterm erts_system_monitor_long_gc;
Uint erts_system_monitor_long_schedule;
@@ -351,7 +351,8 @@ struct erts_system_profile_flags_t erts_system_profile_flags;
typedef enum {
ERTS_PSTT_GC, /* Garbage Collect */
- ERTS_PSTT_CPC /* Check Process Code */
+ ERTS_PSTT_CPC, /* Check Process Code */
+ ERTS_PSTT_COHMQ /* Change off heap message queue */
} ErtsProcSysTaskType;
#define ERTS_MAX_PROC_SYS_TASK_ARGS 2
@@ -611,11 +612,6 @@ erts_pre_init_process(void)
erts_psd_required_locks[ERTS_PSD_SCHED_ID].set_locks
= ERTS_PSD_SCHED_ID_SET_LOCKS;
- erts_psd_required_locks[ERTS_PSD_DIST_ENTRY].get_locks
- = ERTS_PSD_DIST_ENTRY_GET_LOCKS;
- erts_psd_required_locks[ERTS_PSD_DIST_ENTRY].set_locks
- = ERTS_PSD_DIST_ENTRY_SET_LOCKS;
-
erts_psd_required_locks[ERTS_PSD_CALL_TIME_BP].get_locks
= ERTS_PSD_CALL_TIME_BP_GET_LOCKS;
erts_psd_required_locks[ERTS_PSD_CALL_TIME_BP].set_locks
@@ -675,7 +671,6 @@ erts_init_process(int ncpu, int proc_tab_size, int legacy_proc_tab)
last_reductions = 0;
last_exact_reductions = 0;
- erts_default_process_flags = 0;
}
void
@@ -977,7 +972,7 @@ reply_sched_wall_time(void *vswtrp)
Eterm **hpp;
Uint sz, *szp;
ErlOffHeap *ohp = NULL;
- ErlHeapFragment *bp = NULL;
+ ErtsMessage *mp = NULL;
ASSERT(esdp);
#ifdef ERTS_DIRTY_SCHEDULERS
@@ -1033,12 +1028,12 @@ reply_sched_wall_time(void *vswtrp)
if (hpp)
break;
- hp = erts_alloc_message_heap(sz, &bp, &ohp, rp, &rp_locks);
+ mp = erts_alloc_message_heap(rp, &rp_locks, sz, &hp, &ohp);
szp = NULL;
hpp = &hp;
}
- erts_queue_message(rp, &rp_locks, bp, msg, NIL);
+ erts_queue_message(rp, &rp_locks, mp, msg, NIL);
if (swtrp->req_sched == esdp->no)
rp_locks &= ~ERTS_PROC_LOCK_MAIN;
@@ -6257,22 +6252,99 @@ erts_schedule_process(Process *p, erts_aint32_t state, ErtsProcLocks locks)
schedule_process(p, state, locks);
}
-static void
-schedule_process_sys_task(Process *p, erts_aint32_t state, Process *proxy)
+static int
+schedule_process_sys_task(Process *p, erts_aint32_t prio, ErtsProcSysTask *st)
{
- /*
- * Expects status lock to be locked when called, and
- * returns with status lock unlocked...
- */
- erts_aint32_t a = state, n, enq_prio = -1;
+ int res;
+ int locked;
+ ErtsProcSysTaskQs *stqs, *free_stqs;
+ erts_aint32_t state, a, n, enq_prio;
int enqueue; /* < 0 -> use proxy */
- unsigned int prof_runnable_procs = erts_system_profile_flags.runnable_procs;
+ unsigned int prof_runnable_procs;
+
+ res = 1; /* prepare for success */
+ st->next = st->prev = st; /* Prep for empty prio queue */
+ state = erts_smp_atomic32_read_nob(&p->state);
+ prof_runnable_procs = erts_system_profile_flags.runnable_procs;
+ locked = 0;
+ free_stqs = NULL;
+ if (state & ERTS_PSFLG_ACTIVE_SYS)
+ stqs = NULL;
+ else {
+ alloc_qs:
+ stqs = proc_sys_task_queues_alloc();
+ stqs->qmask = 1 << prio;
+ stqs->ncount = 0;
+ stqs->q[PRIORITY_MAX] = NULL;
+ stqs->q[PRIORITY_HIGH] = NULL;
+ stqs->q[PRIORITY_NORMAL] = NULL;
+ stqs->q[PRIORITY_LOW] = NULL;
+ stqs->q[prio] = st;
+ }
+
+ if (!locked) {
+ locked = 1;
+ erts_smp_proc_lock(p, ERTS_PROC_LOCK_STATUS);
+
+ state = erts_smp_atomic32_read_nob(&p->state);
+ if (state & ERTS_PSFLG_EXITING) {
+ free_stqs = stqs;
+ res = 0;
+ goto cleanup;
+ }
+ }
+
+ if (!p->sys_task_qs) {
+ if (stqs)
+ p->sys_task_qs = stqs;
+ else
+ goto alloc_qs;
+ }
+ else {
+ free_stqs = stqs;
+ stqs = p->sys_task_qs;
+ if (!stqs->q[prio]) {
+ stqs->q[prio] = st;
+ stqs->qmask |= 1 << prio;
+ }
+ else {
+ st->next = stqs->q[prio];
+ st->prev = stqs->q[prio]->prev;
+ st->next->prev = st;
+ st->prev->next = st;
+ ASSERT(stqs->qmask & (1 << prio));
+ }
+ }
+
+ if (ERTS_PSFLGS_GET_ACT_PRIO(state) > prio) {
+ erts_aint32_t n, a, e;
+ /* Need to elevate actual prio */
+
+ a = state;
+ do {
+ if (ERTS_PSFLGS_GET_ACT_PRIO(a) <= prio) {
+ n = a;
+ break;
+ }
+ n = e = a;
+ n &= ~ERTS_PSFLGS_ACT_PRIO_MASK;
+ n |= (prio << ERTS_PSFLGS_ACT_PRIO_OFFSET);
+ a = erts_smp_atomic32_cmpxchg_nob(&p->state, n, e);
+ } while (a != e);
+ state = n;
+ }
+
+
+ a = state;
+ enq_prio = -1;
/* Status lock prevents out of order "runnable proc" trace msgs */
ERTS_SMP_LC_ASSERT(ERTS_PROC_LOCK_STATUS & erts_proc_lc_my_proc_locks(p));
- if (!prof_runnable_procs)
+ if (!prof_runnable_procs) {
erts_smp_proc_unlock(p, ERTS_PROC_LOCK_STATUS);
+ locked = 0;
+ }
ASSERT(!(state & ERTS_PSFLG_PROXY));
@@ -6280,8 +6352,10 @@ schedule_process_sys_task(Process *p, erts_aint32_t state, Process *proxy)
erts_aint32_t e;
n = e = a;
- if (a & ERTS_PSFLG_FREE)
+ if (a & ERTS_PSFLG_FREE) {
+ res = 0;
goto cleanup; /* We don't want to schedule free processes... */
+ }
enqueue = ERTS_ENQUEUE_NOT;
n |= ERTS_PSFLG_ACTIVE_SYS;
@@ -6305,29 +6379,24 @@ schedule_process_sys_task(Process *p, erts_aint32_t state, Process *proxy)
}
erts_smp_proc_unlock(p, ERTS_PROC_LOCK_STATUS);
- prof_runnable_procs = 0;
+ locked = 0;
}
- if (enqueue != ERTS_ENQUEUE_NOT) {
- Process *sched_p;
- if (enqueue > 0)
- sched_p = p;
- else {
- sched_p = make_proxy_proc(proxy, p, enq_prio);
- proxy = NULL;
- }
- add2runq(sched_p, n, enq_prio);
- }
+ if (enqueue != ERTS_ENQUEUE_NOT)
+ add2runq(enqueue > 0 ? p : make_proxy_proc(NULL, p, enq_prio),
+ n, enq_prio);
cleanup:
- if (prof_runnable_procs)
+ if (locked)
erts_smp_proc_unlock(p, ERTS_PROC_LOCK_STATUS);
- if (proxy)
- free_proxy_proc(proxy);
+ if (free_stqs)
+ proc_sys_task_queues_free(free_stqs);
ERTS_SMP_LC_ASSERT(!(ERTS_PROC_LOCK_STATUS & erts_proc_lc_my_proc_locks(p)));
+
+ return res;
}
static ERTS_INLINE int
@@ -9151,6 +9220,8 @@ Process *schedule(Process *p, int calls)
} else {
sched_out_proc:
+ ASSERT(!(p->flags & F_DELAY_GC));
+
#ifdef ERTS_SMP
ERTS_SMP_CHK_HAVE_ONLY_MAIN_PROC_LOCK(p);
esdp = p->scheduler_data;
@@ -9664,13 +9735,13 @@ Process *schedule(Process *p, int calls)
}
}
- if (!(state & ERTS_PSFLG_EXITING)
- && ((FLAGS(p) & F_FORCE_GC)
- || (MSO(p).overhead > BIN_VHEAP_SZ(p)))) {
- reds -= erts_garbage_collect(p, 0, p->arg_reg, p->arity);
- if (reds <= 0) {
- p->fcalls = reds;
- goto sched_out_proc;
+ if (ERTS_IS_GC_DESIRED(p)) {
+ if (!(state & ERTS_PSFLG_EXITING) && !(p->flags & F_DISABLE_GC)) {
+ reds -= erts_garbage_collect_nobump(p, 0, p->arg_reg, p->arity);
+ if (reds <= 0) {
+ p->fcalls = reds;
+ goto sched_out_proc;
+ }
}
}
@@ -9710,7 +9781,7 @@ notify_sys_task_executed(Process *c_p, ErtsProcSysTask *st, Eterm st_result)
if (rp) {
ErtsProcLocks rp_locks;
ErlOffHeap *ohp;
- ErlHeapFragment* bp;
+ ErtsMessage *mp;
Eterm *hp, msg, req_id, result;
Uint st_result_sz, hsz;
#ifdef DEBUG
@@ -9722,11 +9793,7 @@ notify_sys_task_executed(Process *c_p, ErtsProcSysTask *st, Eterm st_result)
st_result_sz = is_immed(st_result) ? 0 : size_object(st_result);
hsz = st->req_id_sz + st_result_sz + 4 /* 3-tuple */;
- hp = erts_alloc_message_heap(hsz,
- &bp,
- &ohp,
- rp,
- &rp_locks);
+ mp = erts_alloc_message_heap(rp, &rp_locks, hsz, &hp, &ohp);
#ifdef DEBUG
hp_start = hp;
@@ -9751,7 +9818,7 @@ notify_sys_task_executed(Process *c_p, ErtsProcSysTask *st, Eterm st_result)
ASSERT(hp_start + hsz == hp);
#endif
- erts_queue_message(rp, &rp_locks, bp, msg, NIL);
+ erts_queue_message(rp, &rp_locks, mp, msg, NIL);
if (c_p == rp)
rp_locks &= ~ERTS_PROC_LOCK_MAIN;
@@ -9953,10 +10020,10 @@ execute_sys_tasks(Process *c_p, erts_aint32_t *statep, int in_reds)
else {
if (!garbage_collected) {
FLAGS(c_p) |= F_NEED_FULLSWEEP;
- reds += erts_garbage_collect(c_p,
- 0,
- c_p->arg_reg,
- c_p->arity);
+ reds += erts_garbage_collect_nobump(c_p,
+ 0,
+ c_p->arg_reg,
+ c_p->arity);
garbage_collected = 1;
}
st_res = am_true;
@@ -9973,6 +10040,10 @@ execute_sys_tasks(Process *c_p, erts_aint32_t *statep, int in_reds)
st = NULL;
}
break;
+ case ERTS_PSTT_COHMQ:
+ reds += erts_complete_off_heap_message_queue_change(c_p);
+ st_res = am_true;
+ break;
default:
ERTS_INTERNAL_ERROR("Invalid process sys task type");
st_res = am_false;
@@ -10015,6 +10086,9 @@ cleanup_sys_tasks(Process *c_p, erts_aint32_t in_state, int in_reds)
case ERTS_PSTT_CPC:
st_res = am_false;
break;
+ case ERTS_PSTT_COHMQ:
+ st_res = am_false;
+ break;
default:
ERTS_INTERNAL_ERROR("Invalid process sys task type");
st_res = am_false;
@@ -10033,10 +10107,8 @@ BIF_RETTYPE
erts_internal_request_system_task_3(BIF_ALIST_3)
{
Process *rp = erts_proc_lookup(BIF_ARG_1);
- ErtsProcSysTaskQs *stqs, *free_stqs = NULL;
ErtsProcSysTask *st = NULL;
- erts_aint32_t prio, rp_state;
- int rp_locked;
+ erts_aint32_t prio;
Eterm noproc_res, req_type;
if (!rp && !is_internal_pid(BIF_ARG_1)) {
@@ -10093,7 +10165,6 @@ erts_internal_request_system_task_3(BIF_ALIST_3)
}
st = erts_alloc(ERTS_ALC_T_PROC_SYS_TSK,
ERTS_PROC_SYS_TASK_SIZE(tot_sz));
- st->next = st->prev = st; /* Prep for empty prio queue */
ERTS_INIT_OFF_HEAP(&st->off_heap);
hp = &st->heap[0];
@@ -10137,95 +10208,11 @@ erts_internal_request_system_task_3(BIF_ALIST_3)
goto badarg;
}
- rp_state = erts_smp_atomic32_read_nob(&rp->state);
-
- rp_locked = 0;
-
- free_stqs = NULL;
- if (rp_state & ERTS_PSFLG_ACTIVE_SYS)
- stqs = NULL;
- else {
- alloc_qs:
- stqs = proc_sys_task_queues_alloc();
- stqs->qmask = 1 << prio;
- stqs->ncount = 0;
- stqs->q[PRIORITY_MAX] = NULL;
- stqs->q[PRIORITY_HIGH] = NULL;
- stqs->q[PRIORITY_NORMAL] = NULL;
- stqs->q[PRIORITY_LOW] = NULL;
- stqs->q[prio] = st;
+ if (!schedule_process_sys_task(rp, prio, st)) {
+ noproc:
+ notify_sys_task_executed(BIF_P, st, noproc_res);
}
- if (!rp_locked) {
- rp_locked = 1;
- erts_smp_proc_lock(rp, ERTS_PROC_LOCK_STATUS);
-
- rp_state = erts_smp_atomic32_read_nob(&rp->state);
- if (rp_state & ERTS_PSFLG_EXITING) {
- erts_smp_proc_unlock(rp, ERTS_PROC_LOCK_STATUS);
- rp = NULL;
- free_stqs = stqs;
- goto noproc;
- }
- }
-
- if (!rp->sys_task_qs) {
- if (stqs)
- rp->sys_task_qs = stqs;
- else
- goto alloc_qs;
- }
- else {
- if (stqs)
- free_stqs = stqs;
- stqs = rp->sys_task_qs;
- if (!stqs->q[prio]) {
- stqs->q[prio] = st;
- stqs->qmask |= 1 << prio;
- }
- else {
- st->next = stqs->q[prio];
- st->prev = stqs->q[prio]->prev;
- st->next->prev = st;
- st->prev->next = st;
- ASSERT(stqs->qmask & (1 << prio));
- }
- }
-
- if (ERTS_PSFLGS_GET_ACT_PRIO(rp_state) > prio) {
- erts_aint32_t n, a, e;
- /* Need to elevate actual prio */
-
- a = rp_state;
- do {
- if (ERTS_PSFLGS_GET_ACT_PRIO(a) <= prio) {
- n = a;
- break;
- }
- n = e = a;
- n &= ~ERTS_PSFLGS_ACT_PRIO_MASK;
- n |= (prio << ERTS_PSFLGS_ACT_PRIO_OFFSET);
- a = erts_smp_atomic32_cmpxchg_nob(&rp->state, n, e);
- } while (a != e);
- rp_state = n;
- }
-
- /*
- * schedule_process_sys_task() unlocks status
- * lock on process.
- */
- schedule_process_sys_task(rp, rp_state, NULL);
-
- if (free_stqs)
- proc_sys_task_queues_free(free_stqs);
-
- BIF_RET(am_ok);
-
-noproc:
-
- notify_sys_task_executed(BIF_P, st, noproc_res);
- if (free_stqs)
- proc_sys_task_queues_free(free_stqs);
BIF_RET(am_ok);
badarg:
@@ -10234,11 +10221,35 @@ badarg:
erts_cleanup_offheap(&st->off_heap);
erts_free(ERTS_ALC_T_PROC_SYS_TSK, st);
}
- if (free_stqs)
- proc_sys_task_queues_free(free_stqs);
BIF_ERROR(BIF_P, BADARG);
}
+void
+erts_schedule_complete_off_heap_message_queue_change(Eterm pid)
+{
+ Process *rp = erts_proc_lookup(pid);
+ if (rp) {
+ ErtsProcSysTask *st;
+ erts_aint32_t state;
+ int i;
+
+ st = erts_alloc(ERTS_ALC_T_PROC_SYS_TSK,
+ ERTS_PROC_SYS_TASK_SIZE(0));
+ st->type = ERTS_PSTT_COHMQ;
+ st->requester = NIL;
+ st->reply_tag = NIL;
+ st->req_id = NIL;
+ st->req_id_sz = 0;
+ for (i = 0; i < ERTS_MAX_PROC_SYS_TASK_ARGS; i++)
+ st->arg[i] = NIL;
+ ERTS_INIT_OFF_HEAP(&st->off_heap);
+ state = erts_smp_atomic32_read_nob(&rp->state);
+
+ if (!schedule_process_sys_task(rp, ERTS_PSFLGS_GET_USR_PRIO(state), st))
+ erts_free(ERTS_ALC_T_PROC_SYS_TSK, st);
+ }
+}
+
static void
save_gc_task(Process *c_p, ErtsProcSysTask *st, int prio)
{
@@ -10684,6 +10695,7 @@ erl_create_process(Process* parent, /* Parent of process (default group leader).
Eterm args, /* Arguments for function (must be well-formed list). */
ErlSpawnOpts* so) /* Options for spawn. */
{
+ Uint flags = 0;
ErtsRunQueue *rq = NULL;
Process *p;
Sint arity; /* Number of arguments. */
@@ -10693,6 +10705,10 @@ erl_create_process(Process* parent, /* Parent of process (default group leader).
Eterm res = THE_NON_VALUE;
erts_aint32_t state = 0;
erts_aint32_t prio = (erts_aint32_t) PRIORITY_NORMAL;
+#ifdef SHCOPY_SPAWN
+ erts_shcopy_t info;
+ INITIALIZE_SHCOPY(info);
+#endif
#ifdef ERTS_SMP
erts_smp_proc_lock(parent, ERTS_PROC_LOCKS_ALL_MINOR);
@@ -10721,6 +10737,15 @@ erl_create_process(Process* parent, /* Parent of process (default group leader).
state |= (((prio & ERTS_PSFLGS_PRIO_MASK) << ERTS_PSFLGS_ACT_PRIO_OFFSET)
| ((prio & ERTS_PSFLGS_PRIO_MASK) << ERTS_PSFLGS_USR_PRIO_OFFSET));
+ if (so->flags & SPO_OFF_HEAP_MSGQ) {
+ state |= ERTS_PSFLG_OFF_HEAP_MSGQ;
+ flags |= F_OFF_HEAP_MSGQ;
+ }
+ else if (so->flags & SPO_ON_HEAP_MSGQ) {
+ state |= ERTS_PSFLG_ON_HEAP_MSGQ;
+ flags |= F_ON_HEAP_MSGQ;
+ }
+
if (!rq)
rq = erts_get_runq_proc(parent);
@@ -10739,11 +10764,15 @@ erl_create_process(Process* parent, /* Parent of process (default group leader).
BM_COUNT(processes_spawned);
BM_SWAP_TIMER(system,size);
+#ifdef SHCOPY_SPAWN
+ arg_size = copy_shared_calculate(args, &info);
+#else
arg_size = size_object(args);
+#endif
BM_SWAP_TIMER(size,system);
heap_need = arg_size;
- p->flags = erts_default_process_flags;
+ p->flags = flags;
p->static_flags = 0;
if (so->flags & SPO_SYSTEM_PROC)
@@ -10792,6 +10821,8 @@ erl_create_process(Process* parent, /* Parent of process (default group leader).
p->stop = p->hend = p->heap + sz;
p->htop = p->heap;
p->heap_sz = sz;
+ p->abandoned_heap = NULL;
+ p->live_hf_end = ERTS_INVALID_HFRAG_PTR;
p->catches = 0;
p->bin_vheap_sz = p->min_vheap_size;
@@ -10815,7 +10846,12 @@ erl_create_process(Process* parent, /* Parent of process (default group leader).
BM_MESSAGE(args,p,parent);
BM_START_TIMER(system);
BM_SWAP_TIMER(system,copy);
+#ifdef SHCOPY_SPAWN
+ p->arg_reg[2] = copy_shared_perform(args, arg_size, &info, &p->htop, &p->off_heap);
+ DESTROY_SHCOPY(info);
+#else
p->arg_reg[2] = copy_struct(args, arg_size, &p->htop, &p->off_heap);
+#endif
BM_MESSAGE_COPIED(arg_size);
BM_SWAP_TIMER(copy,system);
p->arity = 3;
@@ -10861,6 +10897,7 @@ erl_create_process(Process* parent, /* Parent of process (default group leader).
p->accessor_bif_timers = NULL;
#endif
p->mbuf = NULL;
+ p->msg_frag = NULL;
p->mbuf_sz = 0;
p->psd = NULL;
p->dictionary = NULL;
@@ -10996,6 +11033,8 @@ void erts_init_empty_process(Process *p)
p->stop = NULL;
p->hend = NULL;
p->heap = NULL;
+ p->abandoned_heap = NULL;
+ p->live_hf_end = ERTS_INVALID_HFRAG_PTR;
p->gen_gcs = 0;
p->max_gen_gcs = 0;
p->min_heap_size = 0;
@@ -11027,6 +11066,7 @@ void erts_init_empty_process(Process *p)
p->old_htop = NULL;
p->old_heap = NULL;
p->mbuf = NULL;
+ p->msg_frag = NULL;
p->mbuf_sz = 0;
p->psd = NULL;
ERTS_P_MONITORS(p) = NULL;
@@ -11115,6 +11155,8 @@ erts_debug_verify_clean_empty_process(Process* p)
ASSERT(p->htop == NULL);
ASSERT(p->stop == NULL);
ASSERT(p->hend == NULL);
+ ASSERT(p->abandoned_heap == NULL);
+ ASSERT(p->live_hf_end == ERTS_INVALID_HFRAG_PTR);
ASSERT(p->heap == NULL);
ASSERT(p->common.id == ERTS_INVALID_PID);
ASSERT(ERTS_TRACER_PROC(p) == NIL);
@@ -11192,9 +11234,10 @@ erts_cleanup_empty_process(Process* p)
static void
delete_process(Process* p)
{
- ErlMessage* mp;
-
+ Eterm *heap;
VERBOSE(DEBUG_PROCESSES, ("Removing process: %T\n",p->common.id));
+ VERBOSE(DEBUG_SHCOPY, ("[pid=%T] delete process: %p %p %p %p\n", p->common.id,
+ HEAP_START(p), HEAP_END(p), OLD_HEAP(p), OLD_HEND(p)));
/* Cleanup psd */
@@ -11218,16 +11261,17 @@ delete_process(Process* p)
* Release heaps. Clobber contents in DEBUG build.
*/
-
-#ifdef DEBUG
- sys_memset(p->heap, DEBUG_BAD_BYTE, p->heap_sz*sizeof(Eterm));
-#endif
-
#ifdef HIPE
hipe_delete_process(&p->hipe);
#endif
- ERTS_HEAP_FREE(ERTS_ALC_T_HEAP, (void*) p->heap, p->heap_sz*sizeof(Eterm));
+ heap = p->abandoned_heap ? p->abandoned_heap : p->heap;
+
+#ifdef DEBUG
+ sys_memset(heap, DEBUG_BAD_BYTE, p->heap_sz*sizeof(Eterm));
+#endif
+
+ ERTS_HEAP_FREE(ERTS_ALC_T_HEAP, (void*) heap, p->heap_sz*sizeof(Eterm));
if (p->old_heap != NULL) {
#ifdef DEBUG
@@ -11246,27 +11290,14 @@ delete_process(Process* p)
free_message_buffer(p->mbuf);
}
+ if (p->msg_frag)
+ erts_cleanup_messages(p->msg_frag);
+
erts_erase_dicts(p);
/* free all pending messages */
- mp = p->msg.first;
- while(mp != NULL) {
- ErlMessage* next_mp = mp->next;
- if (mp->data.attached) {
- if (is_value(mp->m[0]))
- free_message_buffer(mp->data.heap_frag);
- else {
- if (is_not_nil(mp->m[1])) {
- ErlHeapFragment *heap_frag;
- heap_frag = (ErlHeapFragment *) mp->data.dist_ext->ext_endp;
- erts_cleanup_offheap(&heap_frag->off_heap);
- }
- erts_free_dist_ext_copy(mp->data.dist_ext);
- }
- }
- free_message(mp);
- mp = next_mp;
- }
+ erts_cleanup_messages(p->msg.first);
+ p->msg.first = NULL;
ASSERT(!p->nodes_monitors);
ASSERT(!p->suspend_monitors);
@@ -11454,35 +11485,46 @@ static ERTS_INLINE void
send_exit_message(Process *to, ErtsProcLocks *to_locksp,
Eterm exit_term, Uint term_size, Eterm token)
{
- if (token == NIL
-#ifdef USE_VM_PROBES
- || token == am_have_dt_utag
-#endif
- ) {
- Eterm* hp;
- Eterm mess;
- ErlHeapFragment* bp;
- ErlOffHeap *ohp;
-
- hp = erts_alloc_message_heap(term_size, &bp, &ohp, to, to_locksp);
+ ErtsMessage *mp;
+ ErlOffHeap *ohp;
+ Eterm* hp;
+ Eterm mess;
+#ifdef SHCOPY_SEND
+ erts_shcopy_t info;
+#endif
+
+ if (!have_seqtrace(token)) {
+#ifdef SHCOPY_SEND
+ INITIALIZE_SHCOPY(info);
+ term_size = copy_shared_calculate(exit_term, &info);
+ mp = erts_alloc_message_heap(to, to_locksp, term_size, &hp, &ohp);
+ mess = copy_shared_perform(exit_term, term_size, &info, &hp, ohp);
+ DESTROY_SHCOPY(info);
+#else
+ mp = erts_alloc_message_heap(to, to_locksp, term_size, &hp, &ohp);
mess = copy_struct(exit_term, term_size, &hp, ohp);
- erts_queue_message(to, to_locksp, bp, mess, NIL);
+#endif
+ erts_queue_message(to, to_locksp, mp, mess, NIL);
} else {
- ErlHeapFragment* bp;
- Eterm* hp;
- Eterm mess;
Eterm temp_token;
Uint sz_token;
ASSERT(is_tuple(token));
sz_token = size_object(token);
- bp = new_message_buffer(term_size+sz_token);
- hp = bp->mem;
- mess = copy_struct(exit_term, term_size, &hp, &bp->off_heap);
+#ifdef SHCOPY_SEND
+ INITIALIZE_SHCOPY(info);
+ term_size = copy_shared_calculate(exit_term, &info);
+ mp = erts_alloc_message_heap(to, to_locksp, term_size+sz_token, &hp, &ohp);
+ mess = copy_shared_perform(exit_term, term_size, &info, &hp, ohp);
+ DESTROY_SHCOPY(info);
+#else
+ mp = erts_alloc_message_heap(to, to_locksp, term_size+sz_token, &hp, &ohp);
+ mess = copy_struct(exit_term, term_size, &hp, ohp);
+#endif
/* the trace token must in this case be updated by the caller */
seq_trace_output(token, mess, SEQ_TRACE_SEND, to->common.id, NULL);
- temp_token = copy_struct(token, sz_token, &hp, &bp->off_heap);
- erts_queue_message(to, to_locksp, bp, mess, temp_token);
+ temp_token = copy_struct(token, sz_token, &hp, ohp);
+ erts_queue_message(to, to_locksp, mp, mess, temp_token);
}
}
@@ -11591,11 +11633,7 @@ send_exit_signal(Process *c_p, /* current process if and only
if ((state & ERTS_PSFLG_TRAP_EXIT)
&& (reason != am_kill || (flags & ERTS_XSIG_FLG_IGN_KILL))) {
- if (is_not_nil(token)
-#ifdef USE_VM_PROBES
- && token != am_have_dt_utag
-#endif
- && token_update)
+ if (have_seqtrace(token) && token_update)
seq_trace_update_send(token_update);
if (is_value(exit_tuple))
send_exit_message(rp, rp_locks, exit_tuple, exit_tuple_sz, token);
@@ -12258,9 +12296,7 @@ erts_continue_exit_process(Process *p)
erts_proc_dec_refc(p);
}
- dep = ((p->flags & F_DISTRIBUTION)
- ? ERTS_PROC_SET_DIST_ENTRY(p, ERTS_PROC_LOCKS_ALL, NULL)
- : NULL);
+ dep = (p->flags & F_DISTRIBUTION) ? erts_this_dist_entry : NULL;
scb = ERTS_PROC_SET_SAVED_CALLS_BUF(p, ERTS_PROC_LOCKS_ALL, NULL);
pbt = ERTS_PROC_SET_CALL_TIME(p, ERTS_PROC_LOCKS_ALL, NULL);
nif_export = ERTS_PROC_SET_NIF_TRAP_EXPORT(p, ERTS_PROC_LOCKS_ALL, NULL);
@@ -12272,8 +12308,6 @@ erts_continue_exit_process(Process *p)
if (dep) {
erts_do_net_exits(dep, reason);
- if(dep)
- erts_deref_dist_entry(dep);
}
/*
diff --git a/erts/emulator/beam/erl_process.h b/erts/emulator/beam/erl_process.h
index ef58fef102..4bc879eacb 100644
--- a/erts/emulator/beam/erl_process.h
+++ b/erts/emulator/beam/erl_process.h
@@ -785,12 +785,11 @@ erts_smp_reset_max_len(ErtsRunQueue *rq, ErtsRunQueueInfo *rqi)
#define ERTS_PSD_ERROR_HANDLER 0
#define ERTS_PSD_SAVED_CALLS_BUF 1
#define ERTS_PSD_SCHED_ID 2
-#define ERTS_PSD_DIST_ENTRY 3
-#define ERTS_PSD_CALL_TIME_BP 4
-#define ERTS_PSD_DELAYED_GC_TASK_QS 5
-#define ERTS_PSD_NIF_TRAP_EXPORT 6
+#define ERTS_PSD_CALL_TIME_BP 3
+#define ERTS_PSD_DELAYED_GC_TASK_QS 4
+#define ERTS_PSD_NIF_TRAP_EXPORT 5
-#define ERTS_PSD_SIZE 7
+#define ERTS_PSD_SIZE 6
typedef struct {
void *data[ERTS_PSD_SIZE];
@@ -808,9 +807,6 @@ typedef struct {
#define ERTS_PSD_SCHED_ID_GET_LOCKS ERTS_PROC_LOCK_STATUS
#define ERTS_PSD_SCHED_ID_SET_LOCKS ERTS_PROC_LOCK_STATUS
-#define ERTS_PSD_DIST_ENTRY_GET_LOCKS ERTS_PROC_LOCK_MAIN
-#define ERTS_PSD_DIST_ENTRY_SET_LOCKS ERTS_PROC_LOCK_MAIN
-
#define ERTS_PSD_CALL_TIME_BP_GET_LOCKS ERTS_PROC_LOCK_MAIN
#define ERTS_PSD_CALL_TIME_BP_SET_LOCKS ERTS_PROC_LOCK_MAIN
@@ -912,6 +908,7 @@ struct process {
Eterm* stop; /* Stack top */
Eterm* heap; /* Heap start */
Eterm* hend; /* Heap end */
+ Eterm* abandoned_heap;
Uint heap_sz; /* Size of heap in words */
Uint min_heap_size; /* Minimum size of heap (in words). */
Uint min_vheap_size; /* Minimum size of virtual heap (in words). */
@@ -1008,8 +1005,10 @@ struct process {
Uint16 gen_gcs; /* Number of (minor) generational GCs. */
Uint16 max_gen_gcs; /* Max minor gen GCs before fullsweep. */
ErlOffHeap off_heap; /* Off-heap data updated by copy_struct(). */
- ErlHeapFragment* mbuf; /* Pointer to message buffer list */
- Uint mbuf_sz; /* Size of all message buffers */
+ ErlHeapFragment* mbuf; /* Pointer to heap fragment list */
+ ErlHeapFragment* live_hf_end;
+ ErtsMessage *msg_frag; /* Pointer to message fragment list */
+ Uint mbuf_sz; /* Total size of heap fragments and message fragments */
ErtsPSD *psd; /* Rarely used process specific data */
Uint64 bin_vheap_sz; /* Virtual heap block size for binaries */
@@ -1036,6 +1035,7 @@ struct process {
#ifdef CHECK_FOR_HOLES
Eterm* last_htop; /* No need to scan the heap below this point. */
ErlHeapFragment* last_mbuf; /* No need to scan beyond this mbuf. */
+ ErlHeapFragment* heap_hfrag; /* Heap abandoned, htop now lives in this frag */
#endif
#ifdef DEBUG
@@ -1059,6 +1059,7 @@ extern const Process erts_invalid_process;
do { \
(p)->last_htop = 0; \
(p)->last_mbuf = 0; \
+ (p)->heap_hfrag = NULL; \
} while (0)
# define ERTS_HOLE_CHECK(p) erts_check_for_holes((p))
@@ -1136,14 +1137,16 @@ void erts_check_for_holes(Process* p);
#define ERTS_PSFLG_RUNNING_SYS ERTS_PSFLG_BIT(15)
#define ERTS_PSFLG_PROXY ERTS_PSFLG_BIT(16)
#define ERTS_PSFLG_DELAYED_SYS ERTS_PSFLG_BIT(17)
+#define ERTS_PSFLG_OFF_HEAP_MSGQ ERTS_PSFLG_BIT(18)
+#define ERTS_PSFLG_ON_HEAP_MSGQ ERTS_PSFLG_BIT(19)
#ifdef ERTS_DIRTY_SCHEDULERS
-#define ERTS_PSFLG_DIRTY_CPU_PROC ERTS_PSFLG_BIT(18)
-#define ERTS_PSFLG_DIRTY_IO_PROC ERTS_PSFLG_BIT(19)
-#define ERTS_PSFLG_DIRTY_CPU_PROC_IN_Q ERTS_PSFLG_BIT(20)
-#define ERTS_PSFLG_DIRTY_IO_PROC_IN_Q ERTS_PSFLG_BIT(21)
-#define ERTS_PSFLG_MAX (ERTS_PSFLGS_ZERO_BIT_OFFSET + 22)
+#define ERTS_PSFLG_DIRTY_CPU_PROC ERTS_PSFLG_BIT(20)
+#define ERTS_PSFLG_DIRTY_IO_PROC ERTS_PSFLG_BIT(21)
+#define ERTS_PSFLG_DIRTY_CPU_PROC_IN_Q ERTS_PSFLG_BIT(22)
+#define ERTS_PSFLG_DIRTY_IO_PROC_IN_Q ERTS_PSFLG_BIT(23)
+#define ERTS_PSFLG_MAX (ERTS_PSFLGS_ZERO_BIT_OFFSET + 24)
#else
-#define ERTS_PSFLG_MAX (ERTS_PSFLGS_ZERO_BIT_OFFSET + 18)
+#define ERTS_PSFLG_MAX (ERTS_PSFLGS_ZERO_BIT_OFFSET + 20)
#endif
#define ERTS_PSFLGS_IN_PRQ_MASK (ERTS_PSFLG_IN_PRQ_MAX \
@@ -1191,12 +1194,16 @@ void erts_check_for_holes(Process* p);
#define SPO_USE_ARGS 2
#define SPO_MONITOR 4
#define SPO_SYSTEM_PROC 8
+#define SPO_OFF_HEAP_MSGQ 16
+#define SPO_ON_HEAP_MSGQ 32
+
+extern int erts_default_spo_flags;
/*
* The following struct contains options for a process to be spawned.
*/
typedef struct {
- Uint flags;
+ int flags;
int error_code; /* Error code returned from create_process(). */
Eterm mref; /* Monitor ref returned (if SPO_MONITOR was given). */
@@ -1236,7 +1243,6 @@ Eterm* erts_heap_alloc(Process* p, Uint need, Uint xtra);
Eterm* erts_set_hole_marker(Eterm* ptr, Uint sz);
#endif
-extern Uint erts_default_process_flags;
extern erts_smp_rwmtx_t erts_cpu_bind_rwmtx;
/* If any of the erts_system_monitor_* variables are set (enabled),
** erts_system_monitor must be != NIL, to allow testing on just
@@ -1277,7 +1283,23 @@ extern struct erts_system_profile_flags_t erts_system_profile_flags;
#define F_HAVE_BLCKD_MSCHED (1 << 8) /* Process has blocked multi-scheduling */
#define F_P2PNR_RESCHED (1 << 9) /* Process has been rescheduled via erts_pid2proc_not_running() */
#define F_FORCE_GC (1 << 10) /* Force gc at process in-scheduling */
-#define F_DISABLE_GC (1 << 11) /* Disable GC */
+#define F_DISABLE_GC (1 << 11) /* Disable GC (see below) */
+#define F_OFF_HEAP_MSGQ (1 << 12) /* Off heap msg queue */
+#define F_ON_HEAP_MSGQ (1 << 13) /* Off heap msg queue */
+#define F_OFF_HEAP_MSGQ_CHNG (1 << 14) /* Off heap msg queue changing */
+#define F_ABANDONED_HEAP_USE (1 << 15) /* Have usage of abandoned heap */
+#define F_DELAY_GC (1 << 16) /* Similar to disable GC (see below) */
+
+/*
+ * F_DISABLE_GC and F_DELAY_GC are similar. Both will prevent
+ * GC of the process, but it is important to use the right
+ * one:
+ * - F_DISABLE_GC should *only* be used by BIFs. This when
+ * the BIF needs to yield while preventig a GC.
+ * - F_DELAY_GC should only be used when GC is temporarily
+ * disabled while the process is scheduled. A process must
+ * not be scheduled out while F_DELAY_GC is set.
+ */
/* process trace_flags */
#define F_SENSITIVE (1 << 0)
@@ -1611,6 +1633,7 @@ void erts_schedule_thr_prgr_later_cleanup_op(void (*)(void *),
void *,
ErtsThrPrgrLaterOp *,
UWord);
+void erts_schedule_complete_off_heap_message_queue_change(Eterm pid);
#if defined(ERTS_SMP) && defined(ERTS_ENABLE_LOCK_CHECK)
int erts_dbg_check_halloc_lock(Process *p);
@@ -1735,7 +1758,7 @@ Uint erts_debug_nbalance(void);
int erts_debug_wait_completed(Process *c_p, int flags);
-Uint erts_process_memory(Process *c_p);
+Uint erts_process_memory(Process *c_p, int incl_msg_inq);
#ifdef ERTS_SMP
# define ERTS_GET_SCHEDULER_DATA_FROM_PROC(PROC) ((PROC)->scheduler_data)
@@ -1866,11 +1889,6 @@ erts_psd_set(Process *p, ErtsProcLocks plocks, int ix, void *data)
#define ERTS_PROC_SCHED_ID(P, L, ID) \
((UWord) erts_psd_set((P), (L), ERTS_PSD_SCHED_ID, (void *) (ID)))
-#define ERTS_PROC_GET_DIST_ENTRY(P) \
- ((DistEntry *) erts_psd_get((P), ERTS_PSD_DIST_ENTRY))
-#define ERTS_PROC_SET_DIST_ENTRY(P, L, D) \
- ((DistEntry *) erts_psd_set((P), (L), ERTS_PSD_DIST_ENTRY, (void *) (D)))
-
#define ERTS_PROC_GET_SAVED_CALLS_BUF(P) \
((struct saved_calls *) erts_psd_get((P), ERTS_PSD_SAVED_CALLS_BUF))
#define ERTS_PROC_SET_SAVED_CALLS_BUF(P, L, SCB) \
@@ -2050,6 +2068,22 @@ ERTS_GLB_INLINE void erts_smp_xrunq_unlock(ErtsRunQueue *rq, ErtsRunQueue *xrq);
ERTS_GLB_INLINE void erts_smp_runqs_lock(ErtsRunQueue *rq1, ErtsRunQueue *rq2);
ERTS_GLB_INLINE void erts_smp_runqs_unlock(ErtsRunQueue *rq1, ErtsRunQueue *rq2);
+ERTS_GLB_INLINE ErtsMessage *erts_alloc_message_heap_state(Process *pp,
+ erts_aint32_t *psp,
+ ErtsProcLocks *plp,
+ Uint sz,
+ Eterm **hpp,
+ ErlOffHeap **ohpp);
+ERTS_GLB_INLINE ErtsMessage *erts_alloc_message_heap(Process *pp,
+ ErtsProcLocks *plp,
+ Uint sz,
+ Eterm **hpp,
+ ErlOffHeap **ohpp);
+
+ERTS_GLB_INLINE void erts_shrink_message_heap(ErtsMessage **msgpp, Process *pp,
+ Eterm *start_hp, Eterm *used_hp, Eterm *end_hp,
+ Eterm *brefs, Uint brefs_size);
+
#if ERTS_GLB_INLINE_INCL_FUNC_DEF
ERTS_GLB_INLINE
@@ -2198,6 +2232,63 @@ erts_smp_runqs_unlock(ErtsRunQueue *rq1, ErtsRunQueue *rq2)
#endif
}
+ERTS_GLB_INLINE ErtsMessage *
+erts_alloc_message_heap_state(Process *pp,
+ erts_aint32_t *psp,
+ ErtsProcLocks *plp,
+ Uint sz,
+ Eterm **hpp,
+ ErlOffHeap **ohpp)
+{
+ int on_heap;
+
+ if ((*psp) & ERTS_PSFLG_OFF_HEAP_MSGQ) {
+ ErtsMessage *mp = erts_alloc_message(sz, hpp);
+ *ohpp = sz == 0 ? NULL : &mp->hfrag.off_heap;
+ return mp;
+ }
+
+ return erts_try_alloc_message_on_heap(pp, psp, plp, sz, hpp, ohpp, &on_heap);
+}
+
+ERTS_GLB_INLINE ErtsMessage *
+erts_alloc_message_heap(Process *pp,
+ ErtsProcLocks *plp,
+ Uint sz,
+ Eterm **hpp,
+ ErlOffHeap **ohpp)
+{
+ erts_aint32_t state = erts_smp_atomic32_read_nob(&pp->state);
+ return erts_alloc_message_heap_state(pp, &state, plp, sz, hpp, ohpp);
+}
+
+ERTS_GLB_INLINE void
+erts_shrink_message_heap(ErtsMessage **msgpp, Process *pp,
+ Eterm *start_hp, Eterm *used_hp, Eterm *end_hp,
+ Eterm *brefs, Uint brefs_size)
+{
+ ASSERT(start_hp <= used_hp && used_hp <= end_hp);
+ if ((*msgpp)->data.attached == ERTS_MSG_COMBINED_HFRAG)
+ *msgpp = erts_shrink_message(*msgpp, used_hp - start_hp,
+ brefs, brefs_size);
+ else if (!(*msgpp)->data.attached) {
+ ERTS_SMP_LC_ASSERT(ERTS_PROC_LOCK_MAIN
+ & erts_proc_lc_my_proc_locks(pp));
+ HRelease(pp, end_hp, used_hp);
+ }
+ else {
+ ErlHeapFragment *hfrag = (*msgpp)->data.heap_frag;
+ if (start_hp != used_hp)
+ hfrag = erts_resize_message_buffer(hfrag, used_hp - start_hp,
+ brefs, brefs_size);
+ else {
+ free_message_buffer(hfrag);
+ hfrag = NULL;
+ }
+ (*msgpp)->data.heap_frag = hfrag;
+ }
+}
+
#endif /* #if ERTS_GLB_INLINE_INCL_FUNC_DEF */
ERTS_GLB_INLINE ErtsAtomCacheMap *erts_get_atom_cache_map(Process *c_p);
diff --git a/erts/emulator/beam/erl_process_dict.c b/erts/emulator/beam/erl_process_dict.c
index 8606371bdf..da9ebd92ab 100644
--- a/erts/emulator/beam/erl_process_dict.c
+++ b/erts/emulator/beam/erl_process_dict.c
@@ -53,14 +53,17 @@
/* Hash utility macros */
#define HASH_RANGE(PDict) ((PDict)->homeSize + (PDict)->splitPosition)
-#define MAKE_HASH(Term) \
-((is_small(Term)) ? unsigned_val(Term) : \
- ((is_atom(Term)) ? \
- (atom_tab(atom_val(term))->slot.bucket.hvalue) : \
- make_hash2(Term)))
+#define MAKE_HASH(Term) \
+ ((is_small(Term)) ? unsigned_val(Term) : \
+ ((is_atom(Term)) ? \
+ (atom_tab(atom_val(Term))->slot.bucket.hvalue) : \
+ make_internal_hash(Term)))
#define PD_SZ2BYTES(Sz) (sizeof(ProcDict) + ((Sz) - 1)*sizeof(Eterm))
+#define pd_hash_value(Pdict, Key) \
+ pd_hash_value_to_ix(Pdict, MAKE_HASH((Key)))
+
/* Memory allocation macros */
#define PD_ALLOC(Sz) \
erts_alloc(ERTS_ALC_T_PROC_DICT, (Sz))
@@ -82,6 +85,7 @@
*/
static void pd_hash_erase(Process *p, Eterm id, Eterm *ret);
static void pd_hash_erase_all(Process *p);
+static Eterm pd_hash_get_with_hval(Process *p, Eterm bucket, Eterm id);
static Eterm pd_hash_get_keys(Process *p, Eterm value);
static Eterm pd_hash_get_all_keys(Process *p, ProcDict *pd);
static Eterm pd_hash_get_all(Process *p, ProcDict *pd);
@@ -93,7 +97,7 @@ static void grow(Process *p);
static void array_shrink(ProcDict **ppd, unsigned int need);
static Eterm array_put(ProcDict **ppdict, unsigned int ndx, Eterm term);
-static unsigned int pd_hash_value(ProcDict *pdict, Eterm term);
+static unsigned int pd_hash_value_to_ix(ProcDict *pdict, Uint32 hx);
static unsigned int next_array_size(unsigned int need);
/*
@@ -390,40 +394,55 @@ static void pd_hash_erase_all(Process *p)
}
}
+Eterm erts_pd_hash_get_with_hx(Process *p, Uint32 hx, Eterm id)
+{
+ unsigned int hval;
+ ProcDict *pd = p->dictionary;
+
+ if (pd == NULL)
+ return am_undefined;
+ hval = pd_hash_value_to_ix(pd, hx);
+ return pd_hash_get_with_hval(p, ARRAY_GET(pd, hval), id);
+}
+
Eterm erts_pd_hash_get(Process *p, Eterm id)
{
unsigned int hval;
- Eterm tmp;
ProcDict *pd = p->dictionary;
if (pd == NULL)
return am_undefined;
hval = pd_hash_value(pd, id);
- tmp = ARRAY_GET(pd, hval);
- if (is_boxed(tmp)) { /* Tuple */
- ASSERT(is_tuple(tmp));
- if (EQ(tuple_val(tmp)[1], id)) {
- return tuple_val(tmp)[2];
+ return pd_hash_get_with_hval(p, ARRAY_GET(pd, hval), id);
+}
+
+Eterm pd_hash_get_with_hval(Process *p, Eterm bucket, Eterm id)
+{
+ if (is_boxed(bucket)) { /* Tuple */
+ ASSERT(is_tuple(bucket));
+ if (EQ(tuple_val(bucket)[1], id)) {
+ return tuple_val(bucket)[2];
}
- } else if (is_list(tmp)) {
- for (; tmp != NIL && !EQ(tuple_val(TCAR(tmp))[1], id); tmp = TCDR(tmp)) {
+ } else if (is_list(bucket)) {
+ for (; bucket != NIL && !EQ(tuple_val(TCAR(bucket))[1], id); bucket = TCDR(bucket)) {
;
}
- if (tmp != NIL) {
- return tuple_val(TCAR(tmp))[2];
+ if (bucket != NIL) {
+ return tuple_val(TCAR(bucket))[2];
}
- } else if (is_not_nil(tmp)) {
+ } else if (is_not_nil(bucket)) {
#ifdef DEBUG
erts_fprintf(stderr,
"Process dictionary for process %T is broken, trying to "
"display term found in line %d:\n"
- "%T\n", p->common.id, __LINE__, tmp);
+ "%T\n", p->common.id, __LINE__, bucket);
#endif
erl_exit(1, "Damaged process dictionary found during get/1.");
}
return am_undefined;
}
+
#define PD_GET_TKEY(Dst,Src) \
do { \
ASSERT(is_tuple((Src))); \
@@ -583,7 +602,7 @@ static Eterm pd_hash_put(Process *p, Eterm id, Eterm value)
root[0] = id;
root[1] = value;
root[2] = old;
- BUMP_REDS(p, erts_garbage_collect(p, needed, root, 3));
+ erts_garbage_collect(p, needed, root, 3);
id = root[0];
value = root[1];
old = root[2];
@@ -715,7 +734,7 @@ static void shrink(Process *p, Eterm* ret)
needed = 2*erts_list_length(hi);
}
if (HeapWordsLeft(p) < needed) {
- BUMP_REDS(p, erts_garbage_collect(p, needed, ret, 1));
+ erts_garbage_collect(p, needed, ret, 1);
hi = pd->data[(pd->splitPosition + pd->homeSize)];
lo = pd->data[pd->splitPosition];
}
@@ -811,7 +830,7 @@ static void grow(Process *p)
}
}
if (HeapWordsLeft(p) < needed) {
- BUMP_REDS(p, erts_garbage_collect(p, needed, 0, 0));
+ erts_garbage_collect(p, needed, 0, 0);
}
#ifdef DEBUG
hp_limit = p->htop + needed;
@@ -932,17 +951,16 @@ static Eterm array_put(ProcDict **ppdict, unsigned int ndx, Eterm term)
** Basic utilities
*/
-static unsigned int pd_hash_value(ProcDict *pdict, Eterm term)
+static unsigned int pd_hash_value_to_ix(ProcDict *pdict, Uint32 hx)
{
- Uint hash, high;
-
- hash = MAKE_HASH(term);
- high = hash % (pdict->homeSize*2);
+ Uint high;
+ high = hx % (pdict->homeSize*2);
if (high >= HASH_RANGE(pdict))
- return hash % pdict->homeSize;
+ return hx % pdict->homeSize;
return high;
}
+
static unsigned int next_array_size(unsigned int need)
{
static unsigned int tab[] =
diff --git a/erts/emulator/beam/erl_process_dict.h b/erts/emulator/beam/erl_process_dict.h
index cc53800eb5..9aa21b7c38 100644
--- a/erts/emulator/beam/erl_process_dict.h
+++ b/erts/emulator/beam/erl_process_dict.h
@@ -39,5 +39,6 @@ void erts_deep_dictionary_dump(int to, void *to_arg,
Eterm erts_dictionary_copy(struct process *p, ProcDict *pd);
Eterm erts_pd_hash_get(struct process *p, Eterm id);
+Eterm erts_pd_hash_get_with_hx(Process *p, Uint32 hx, Eterm id);
#endif
diff --git a/erts/emulator/beam/erl_process_dump.c b/erts/emulator/beam/erl_process_dump.c
index 3b8ae11e94..71396561a3 100644
--- a/erts/emulator/beam/erl_process_dump.c
+++ b/erts/emulator/beam/erl_process_dump.c
@@ -78,13 +78,14 @@ erts_deep_process_dump(int to, void *to_arg)
dump_binaries(to, to_arg, all_binaries);
}
-Uint erts_process_memory(Process *p) {
- ErlMessage *mp;
+Uint erts_process_memory(Process *p, int incl_msg_inq) {
+ ErtsMessage *mp;
Uint size = 0;
struct saved_calls *scb;
size += sizeof(Process);
- ERTS_SMP_MSGQ_MV_INQ2PRIVQ(p);
+ if (incl_msg_inq)
+ ERTS_SMP_MSGQ_MV_INQ2PRIVQ(p);
erts_doforall_links(ERTS_P_LINKS(p), &erts_one_link_size, &size);
erts_doforall_monitors(ERTS_P_MONITORS(p), &erts_one_mon_size, &size);
@@ -92,7 +93,7 @@ Uint erts_process_memory(Process *p) {
if (p->old_hend && p->old_heap)
size += (p->old_hend - p->old_heap) * sizeof(Eterm);
- size += p->msg.len * sizeof(ErlMessage);
+ size += p->msg.len * sizeof(ErtsMessage);
for (mp = p->msg.first; mp; mp = mp->next)
if (mp->data.attached)
@@ -119,7 +120,7 @@ static void
dump_process_info(int to, void *to_arg, Process *p)
{
Eterm* sp;
- ErlMessage* mp;
+ ErtsMessage* mp;
int yreg = -1;
ERTS_SMP_MSGQ_MV_INQ2PRIVQ(p);
@@ -657,6 +658,8 @@ erts_dump_extended_process_state(int to, void *to_arg, erts_aint32_t psflg) {
erts_print(to, to_arg, "PROXY"); break;
case ERTS_PSFLG_DELAYED_SYS:
erts_print(to, to_arg, "DELAYED_SYS"); break;
+ case ERTS_PSFLG_OFF_HEAP_MSGQ:
+ erts_print(to, to_arg, "OFF_HEAP_MSGQ"); break;
#ifdef ERTS_DIRTY_SCHEDULERS
case ERTS_PSFLG_DIRTY_CPU_PROC:
erts_print(to, to_arg, "DIRTY_CPU_PROC"); break;
diff --git a/erts/emulator/beam/erl_term.c b/erts/emulator/beam/erl_term.c
index ed302fa2fa..e31d3a951d 100644
--- a/erts/emulator/beam/erl_term.c
+++ b/erts/emulator/beam/erl_term.c
@@ -28,6 +28,37 @@
#include <stdlib.h>
#include <stdio.h>
+void
+erts_set_literal_tag(Eterm *term, Eterm *hp_start, Eterm hsz)
+{
+#ifdef TAG_LITERAL_PTR
+ Eterm *hp_end, *hp;
+
+ hp_end = hp_start + hsz;
+ hp = hp_start;
+
+ while (hp < hp_end) {
+ switch (primary_tag(*hp)) {
+ case TAG_PRIMARY_BOXED:
+ case TAG_PRIMARY_LIST:
+ *hp |= TAG_LITERAL_PTR;
+ break;
+ case TAG_PRIMARY_HEADER:
+ if (header_is_thing(*hp)) {
+ hp += thing_arityval(*hp);
+ }
+ break;
+ default:
+ break;
+ }
+
+ hp++;
+ }
+ if (is_boxed(*term) || is_list(*term))
+ *term |= TAG_LITERAL_PTR;
+#endif
+}
+
__decl_noreturn static void __noreturn
et_abort(const char *expr, const char *file, unsigned line)
{
diff --git a/erts/emulator/beam/erl_term.h b/erts/emulator/beam/erl_term.h
index 01ef567dcd..2b28762db5 100644
--- a/erts/emulator/beam/erl_term.h
+++ b/erts/emulator/beam/erl_term.h
@@ -21,6 +21,8 @@
#ifndef __ERL_TERM_H
#define __ERL_TERM_H
+#include "erl_mmap.h"
+
typedef UWord Wterm; /* Full word terms */
struct erl_node_; /* Declared in erl_node_tables.h */
@@ -48,6 +50,24 @@ struct erl_node_; /* Declared in erl_node_tables.h */
#define _ET_APPLY(F,X) _unchecked_##F(X)
#endif
+#if defined(ARCH_64)
+# define TAG_PTR_MASK__ 0x7
+# if !defined(ERTS_HAVE_OS_PHYSICAL_MEMORY_RESERVATION)
+# ifdef HIPE
+# error Hipe on 64-bit needs a real mmap as it does not support the literal tag
+# endif
+# define TAG_LITERAL_PTR 0x4
+# else
+# undef TAG_LITERAL_PTR
+# endif
+#elif defined(ARCH_32)
+# define TAG_PTR_MASK__ 0x3
+# undef TAG_LITERAL_PTR
+#else
+# error Not supported arch
+#endif
+
+
#define _TAG_PRIMARY_SIZE 2
#define _TAG_PRIMARY_MASK 0x3
#define TAG_PRIMARY_HEADER 0x0
@@ -165,10 +185,11 @@ struct erl_node_; /* Declared in erl_node_tables.h */
/* boxed object access methods */
-#define _is_taggable_pointer(x) (((Uint)(x) & 0x3) == 0)
+#define _is_taggable_pointer(x) (((Uint)(x) & TAG_PTR_MASK__) == 0)
+
#define _boxed_precond(x) (is_boxed(x))
-#define _is_aligned(x) (((Uint)(x) & 0x3) == 0)
+#define _is_aligned(x) (((Uint)(x) & TAG_PTR_MASK__) == 0)
#define _unchecked_make_boxed(x) ((Uint)(x) + TAG_PRIMARY_BOXED)
_ET_DECLARE_CHECKED(Eterm,make_boxed,const Eterm*)
#define make_boxed(x) _ET_APPLY(make_boxed,(x))
@@ -180,7 +201,11 @@ _ET_DECLARE_CHECKED(int,is_boxed,Eterm)
#else
#define is_boxed(x) (((x) & _TAG_PRIMARY_MASK) == TAG_PRIMARY_BOXED)
#endif
+#ifdef TAG_LITERAL_PTR
+#define _unchecked_boxed_val(x) _unchecked_ptr_val(x)
+#else
#define _unchecked_boxed_val(x) ((Eterm*) ((x) - TAG_PRIMARY_BOXED))
+#endif
_ET_DECLARE_CHECKED(Eterm*,boxed_val,Wterm)
#define boxed_val(x) _ET_APPLY(boxed_val,(x))
@@ -198,7 +223,11 @@ _ET_DECLARE_CHECKED(int,is_not_list,Eterm)
#define is_not_list(x) (!is_list((x)))
#endif
#define _list_precond(x) (is_list(x))
+#ifdef TAG_LITERAL_PTR
+#define _unchecked_list_val(x) _unchecked_ptr_val(x)
+#else
#define _unchecked_list_val(x) ((Eterm*) ((x) - TAG_PRIMARY_LIST))
+#endif
_ET_DECLARE_CHECKED(Eterm*,list_val,Wterm)
#define list_val(x) _ET_APPLY(list_val,(x))
@@ -209,13 +238,20 @@ _ET_DECLARE_CHECKED(Eterm*,list_val,Wterm)
#define CDR(x) ((x)[1])
/* generic tagged pointer (boxed or list) access methods */
-#define _unchecked_ptr_val(x) ((Eterm*) ((x) & ~((Uint) 0x3)))
+#define _unchecked_ptr_val(x) ((Eterm*) ((x) & ~((Uint) TAG_PTR_MASK__)))
#define ptr_val(x) _unchecked_ptr_val((x)) /*XXX*/
#define _unchecked_offset_ptr(x,offs) ((x)+((offs)*sizeof(Eterm)))
#define offset_ptr(x,offs) _unchecked_offset_ptr(x,offs) /*XXX*/
#define _unchecked_byte_offset_ptr(x,byte_offs) ((x)+(offs))
#define byte_offset_ptr(x,offs) _unchecked_byte_offset_ptr(x,offs) /*XXX*/
+#ifdef TAG_LITERAL_PTR
+#define _unchecked_is_not_literal_ptr(x) (!((x) & TAG_LITERAL_PTR))
+#define is_not_literal_ptr(x) _unchecked_is_not_literal_ptr((x)) /*XXX*/
+#define is_literal_ptr(x) (!is_not_literal_ptr((x))) /*XXX*/
+#endif
+
+
/* fixnum ("small") access methods */
#if defined(ARCH_64)
#define SMALL_BITS (64-4)
@@ -1114,5 +1150,7 @@ extern unsigned tag_val_def(Wterm);
#define is_same(A,B) ((A)==(B))
+void erts_set_literal_tag(Eterm *term, Eterm *hp_start, Eterm hsz);
+
#endif /* __ERL_TERM_H */
diff --git a/erts/emulator/beam/erl_time_sup.c b/erts/emulator/beam/erl_time_sup.c
index 7327e0b48c..7ec64506e8 100644
--- a/erts/emulator/beam/erl_time_sup.c
+++ b/erts/emulator/beam/erl_time_sup.c
@@ -1919,15 +1919,16 @@ send_time_offset_changed_notifications(void *new_offsetp)
ErtsProcLocks rp_locks = ERTS_PROC_LOCK_LINK;
erts_smp_proc_lock(rp, ERTS_PROC_LOCK_LINK);
if (erts_lookup_monitor(ERTS_P_MONITORS(rp), ref)) {
- ErlHeapFragment *bp;
+ ErtsMessage *mp;
ErlOffHeap *ohp;
Eterm message;
- hp = erts_alloc_message_heap(hsz, &bp, &ohp, rp, &rp_locks);
+ mp = erts_alloc_message_heap(rp, &rp_locks,
+ hsz, &hp, &ohp);
*patch_refp = ref;
ASSERT(hsz == size_object(message_template));
message = copy_struct(message_template, hsz, &hp, ohp);
- erts_queue_message(rp, &rp_locks, bp, message, NIL);
+ erts_queue_message(rp, &rp_locks, mp, message, NIL);
}
erts_smp_proc_unlock(rp, rp_locks);
}
diff --git a/erts/emulator/beam/erl_trace.c b/erts/emulator/beam/erl_trace.c
index e9dd96efc4..b774ba97af 100644
--- a/erts/emulator/beam/erl_trace.c
+++ b/erts/emulator/beam/erl_trace.c
@@ -114,15 +114,10 @@ void erts_init_trace(void) {
static Eterm system_seq_tracer;
-#ifdef ERTS_SMP
#define ERTS_ALLOC_SYSMSG_HEAP(SZ, BPP, OHPP, UNUSED) \
(*(BPP) = new_message_buffer((SZ)), \
*(OHPP) = &(*(BPP))->off_heap, \
(*(BPP))->mem)
-#else
-#define ERTS_ALLOC_SYSMSG_HEAP(SZ, BPP, OHPP, RPP) \
- erts_alloc_message_heap((SZ), (BPP), (OHPP), (RPP), 0)
-#endif
#ifdef ERTS_SMP
#define ERTS_ENQ_TRACE_MSG(FPID, TPID, MSG, BP) \
@@ -131,8 +126,12 @@ do { \
enqueue_sys_msg_unlocked(SYS_MSG_TYPE_TRACE, (FPID), (TPID), (MSG), (BP)); \
} while(0)
#else
-#define ERTS_ENQ_TRACE_MSG(FPID, TPROC, MSG, BP) \
- erts_queue_message((TPROC), NULL, (BP), (MSG), NIL)
+#define ERTS_ENQ_TRACE_MSG(FPID, TPROC, MSG, BP) \
+ do { \
+ ErtsMessage *mp__ = erts_alloc_message(0, NULL); \
+ mp__->data.heap_frag = (BP); \
+ erts_queue_message((TPROC), NULL, mp__, (MSG), NIL); \
+ } while (0)
#endif
/*
@@ -591,11 +590,9 @@ send_to_port(Process *c_p, Eterm message,
static void
profile_send(Eterm from, Eterm message) {
Uint sz = 0;
- ErlHeapFragment *bp = NULL;
Uint *hp = NULL;
Eterm msg = NIL;
Process *profile_p = NULL;
- ErlOffHeap *off_heap = NULL;
Eterm profiler = erts_get_system_profile();
@@ -621,6 +618,7 @@ profile_send(Eterm from, Eterm message) {
}
} else {
+ ErtsMessage *mp;
ASSERT(is_internal_pid(profiler));
profile_p = erts_proc_lookup(profiler);
@@ -629,10 +627,13 @@ profile_send(Eterm from, Eterm message) {
return;
sz = size_object(message);
- hp = erts_alloc_message_heap(sz, &bp, &off_heap, profile_p, 0);
- msg = copy_struct(message, sz, &hp, &bp->off_heap);
-
- erts_queue_message(profile_p, NULL, bp, msg, NIL);
+ mp = erts_alloc_message(sz, &hp);
+ if (sz == 0)
+ msg = message;
+ else
+ msg = copy_struct(message, sz, &hp, &mp->hfrag.off_heap);
+
+ erts_queue_message(profile_p, NULL, mp, msg, NIL);
}
}
@@ -1045,11 +1046,7 @@ seq_trace_update_send(Process *p)
{
Eterm seq_tracer = erts_get_system_seq_tracer();
ASSERT((is_tuple(SEQ_TRACE_TOKEN(p)) || is_nil(SEQ_TRACE_TOKEN(p))));
- if ( (p->common.id == seq_tracer) || (SEQ_TRACE_TOKEN(p) == NIL)
-#ifdef USE_VM_PROBES
- || (SEQ_TRACE_TOKEN(p) == am_have_dt_utag)
-#endif
- ) {
+ if ((p->common.id == seq_tracer) || have_no_seqtrace(SEQ_TRACE_TOKEN(p))) {
return 0;
}
SEQ_TRACE_TOKEN_SENDER(p) = p->common.id;
@@ -1233,7 +1230,11 @@ seq_trace_output_generic(Eterm token, Eterm msg, Uint type,
erts_smp_mtx_unlock(&smq_mtx);
#else
/* trace_token must be NIL here */
- erts_queue_message(tracer, NULL, bp, mess, NIL);
+ {
+ ErtsMessage *mp = erts_alloc_message(0, NULL);
+ mp->data.heap_frag = bp;
+ erts_queue_message(tracer, NULL, mp, mess, NIL);
+ }
#endif
}
}
@@ -2308,7 +2309,11 @@ monitor_long_schedule_proc(Process *p, BeamInstr *in_fp, BeamInstr *out_fp, Uint
#ifdef ERTS_SMP
enqueue_sys_msg(SYS_MSG_TYPE_SYSMON, p->common.id, NIL, msg, bp);
#else
- erts_queue_message(monitor_p, NULL, bp, msg, NIL);
+ {
+ ErtsMessage *mp = erts_alloc_message(0, NULL);
+ mp->data.heap_frag = bp;
+ erts_queue_message(monitor_p, NULL, mp, msg, NIL);
+ }
#endif
}
void
@@ -2369,7 +2374,11 @@ monitor_long_schedule_port(Port *pp, ErtsPortTaskType type, Uint time)
#ifdef ERTS_SMP
enqueue_sys_msg(SYS_MSG_TYPE_SYSMON, pp->common.id, NIL, msg, bp);
#else
- erts_queue_message(monitor_p, NULL, bp, msg, NIL);
+ {
+ ErtsMessage *mp = erts_alloc_message(0, NULL);
+ mp->data.heap_frag = bp;
+ erts_queue_message(monitor_p, NULL, mp, msg, NIL);
+ }
#endif
}
@@ -2440,7 +2449,11 @@ monitor_long_gc(Process *p, Uint time) {
#ifdef ERTS_SMP
enqueue_sys_msg(SYS_MSG_TYPE_SYSMON, p->common.id, NIL, msg, bp);
#else
- erts_queue_message(monitor_p, NULL, bp, msg, NIL);
+ {
+ ErtsMessage *mp = erts_alloc_message(0, NULL);
+ mp->data.heap_frag = bp;
+ erts_queue_message(monitor_p, NULL, mp, msg, NIL);
+ }
#endif
}
@@ -2511,7 +2524,11 @@ monitor_large_heap(Process *p) {
#ifdef ERTS_SMP
enqueue_sys_msg(SYS_MSG_TYPE_SYSMON, p->common.id, NIL, msg, bp);
#else
- erts_queue_message(monitor_p, NULL, bp, msg, NIL);
+ {
+ ErtsMessage *mp = erts_alloc_message(0, NULL);
+ mp->data.heap_frag = bp;
+ erts_queue_message(monitor_p, NULL, mp, msg, NIL);
+ }
#endif
}
@@ -2539,7 +2556,11 @@ monitor_generic(Process *p, Eterm type, Eterm spec) {
#ifdef ERTS_SMP
enqueue_sys_msg(SYS_MSG_TYPE_SYSMON, p->common.id, NIL, msg, bp);
#else
- erts_queue_message(monitor_p, NULL, bp, msg, NIL);
+ {
+ ErtsMessage *mp = erts_alloc_message(0, NULL);
+ mp->data.heap_frag = bp;
+ erts_queue_message(monitor_p, NULL, mp, msg, NIL);
+ }
#endif
}
@@ -3331,8 +3352,11 @@ sys_msg_dispatcher_func(void *unused)
goto failure;
}
else {
+ ErtsMessage *mp;
queue_proc_msg:
- erts_queue_message(proc,&proc_locks,smqp->bp,smqp->msg,NIL);
+ mp = erts_alloc_message(0, NULL);
+ mp->data.heap_frag = smqp->bp;
+ erts_queue_message(proc,&proc_locks,mp,smqp->msg,NIL);
#ifdef DEBUG_PRINTOUTS
erts_fprintf(stderr, "delivered\n");
#endif
diff --git a/erts/emulator/beam/external.c b/erts/emulator/beam/external.c
index c3e93d1ad2..58010dcb72 100644
--- a/erts/emulator/beam/external.c
+++ b/erts/emulator/beam/external.c
@@ -1179,7 +1179,7 @@ typedef struct {
ErtsHeapFactory factory;
int remaining_n;
char* remaining_bytes;
- Eterm* maps_list;
+ ErtsWStack flat_maps;
ErtsPStack hamt_array;
} B2TDecodeContext;
@@ -1519,7 +1519,7 @@ static BIF_RETTYPE binary_to_term_int(Process* p, Uint32 flags, Eterm bin, Binar
ctx->u.dc.res = (Eterm) (UWord) NULL;
ctx->u.dc.next = &ctx->u.dc.res;
erts_factory_proc_prealloc_init(&ctx->u.dc.factory, p, ctx->heap_size);
- ctx->u.dc.maps_list = NULL;
+ ctx->u.dc.flat_maps.wstart = NULL;
ctx->u.dc.hamt_array.pstart = NULL;
ctx->state = B2TDecode;
/*fall through*/
@@ -2919,7 +2919,7 @@ dec_term(ErtsDistExternal *edep,
int n;
ErtsAtomEncoding char_enc;
register Eterm* hp; /* Please don't take the address of hp */
- Eterm *maps_list; /* for preprocessing of small maps */
+ DECLARE_WSTACK(flat_maps); /* for preprocessing of small maps */
Eterm* next;
SWord reds;
#ifdef DEBUG
@@ -2931,7 +2931,6 @@ dec_term(ErtsDistExternal *edep,
next = ctx->u.dc.next;
ep = ctx->u.dc.ep;
factory = &ctx->u.dc.factory;
- maps_list = ctx->u.dc.maps_list;
if (ctx->state != B2TDecode) {
int n_limit = reds;
@@ -3007,15 +3006,18 @@ dec_term(ErtsDistExternal *edep,
}
}
PSTACK_CHANGE_ALLOCATOR(hamt_array, ERTS_ALC_T_SAVED_ESTACK);
+ WSTACK_CHANGE_ALLOCATOR(flat_maps, ERTS_ALC_T_SAVED_ESTACK);
if (ctx->u.dc.hamt_array.pstart) {
PSTACK_RESTORE(hamt_array, &ctx->u.dc.hamt_array);
}
+ if (ctx->u.dc.flat_maps.wstart) {
+ WSTACK_RESTORE(flat_maps, &ctx->u.dc.flat_maps);
+ }
}
else {
reds = ERTS_SWORD_MAX;
next = objp;
*next = (Eterm) (UWord) NULL;
- maps_list = NULL;
}
hp = factory->hp;
@@ -3571,14 +3573,8 @@ dec_term_atom_common:
* vptr, last word for values
*/
- /*
- * Use thing_word to link through decoded maps.
- * The list of maps is for later validation.
- */
-
- mp->thing_word = (Eterm) maps_list;
- maps_list = (Eterm *) mp;
-
+ WSTACK_PUSH(flat_maps, (UWord)mp);
+ mp->thing_word = MAP_HEADER_FLATMAP;
mp->size = size;
mp->keys = keys;
*objp = make_flatmap(mp);
@@ -3827,7 +3823,9 @@ dec_term_atom_common:
ctx->u.dc.ep = ep;
ctx->u.dc.next = next;
ctx->u.dc.factory.hp = hp;
- ctx->u.dc.maps_list = maps_list;
+ if (!WSTACK_ISEMPTY(flat_maps)) {
+ WSTACK_SAVE(flat_maps, &ctx->u.dc.flat_maps);
+ }
if (!PSTACK_IS_EMPTY(hamt_array)) {
PSTACK_SAVE(hamt_array, &ctx->u.dc.hamt_array);
}
@@ -3841,18 +3839,6 @@ dec_term_atom_common:
}
}
- /* Iterate through all the maps and check for validity and sort keys
- * - done here for when we know it is complete.
- */
-
- while (maps_list) {
- next = (Eterm *) *maps_list;
- *maps_list = MAP_HEADER_FLATMAP;
- if (!erts_validate_and_sort_flatmap((flatmap_t*)maps_list))
- goto error;
- maps_list = next;
- }
-
ASSERT(hp <= factory->hp_end
|| (factory->mode == FACTORY_CLOSED && is_immed(*dbg_resultp)));
factory->hp = hp;
@@ -3861,20 +3847,31 @@ dec_term_atom_common:
*/
if (!PSTACK_IS_EMPTY(hamt_array)) {
- do {
- struct dec_term_hamt* hamt = PSTACK_TOP(hamt_array);
-
- *hamt->objp = erts_hashmap_from_array(factory,
- hamt->leaf_array,
- hamt->size,
- 1);
- if (is_non_value(*hamt->objp))
- goto error_hamt;
-
- (void) PSTACK_POP(hamt_array);
- } while (!PSTACK_IS_EMPTY(hamt_array));
- PSTACK_DESTROY(hamt_array);
+ do {
+ struct dec_term_hamt* hamt = PSTACK_TOP(hamt_array);
+
+ *hamt->objp = erts_hashmap_from_array(factory,
+ hamt->leaf_array,
+ hamt->size,
+ 1);
+ if (is_non_value(*hamt->objp))
+ goto error_hamt;
+
+ (void) PSTACK_POP(hamt_array);
+ } while (!PSTACK_IS_EMPTY(hamt_array));
+ PSTACK_DESTROY(hamt_array);
+ }
+
+ /* Iterate through all the (flat)maps and check for validity and sort keys
+ * - done here for when we know it is complete.
+ */
+
+ while(!WSTACK_ISEMPTY(flat_maps)) {
+ next = (Eterm *)WSTACK_POP(flat_maps);
+ if (!erts_validate_and_sort_flatmap((flatmap_t*)next))
+ goto error;
}
+ WSTACK_DESTROY(flat_maps);
ASSERT((Eterm*)*dbg_resultp != NULL);
@@ -3900,6 +3897,7 @@ error_hamt:
ctx->state = B2TDecodeFail;
ctx->reds = reds;
}
+ WSTACK_DESTROY(flat_maps);
return NULL;
}
diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h
index 4352d5758b..0bf5988244 100644
--- a/erts/emulator/beam/global.h
+++ b/erts/emulator/beam/global.h
@@ -380,7 +380,7 @@ extern int bif_reductions; /* reductions + fcalls (when doing call_bif) */
extern int stackdump_on_exit;
/*
- * Here is an implementation of a lightweiht stack.
+ * Here is an implementation of a lightweight stack.
*
* Use it like this:
*
@@ -845,6 +845,94 @@ do {\
} while(0)
+/*
+ * An implementation of lightweight unbounded queues,
+ * using a circular dynamic array.
+ * It does not include support for change_allocator.
+ *
+ * Use it like this:
+ *
+ * DECLARE_EQUEUE(Queue) (At the start of a block)
+ * ...
+ * EQUEUE_PUT(Queue, Term)
+ * ...
+ * if (EQUEUE_ISEMPTY(Queue)) {
+ * Queue is empty
+ * } else {
+ * Term = EQUEUE_GET(Stack);
+ * Process popped Term here
+ * }
+ * ...
+ * DESTROY_EQUEUE(Queue)
+ */
+
+typedef struct {
+ Eterm* start;
+ Eterm* front;
+ Eterm* back;
+ int possibly_empty;
+ Eterm* end;
+ ErtsAlcType_t alloc_type;
+} ErtsEQueue;
+
+#define DEF_EQUEUE_SIZE (16)
+
+void erl_grow_equeue(ErtsEQueue*, Eterm* def_queue);
+#define EQUE_CONCAT(a,b) a##b
+#define EQUE_DEF_QUEUE(q) EQUE_CONCAT(q,_default_equeue)
+
+#define DECLARE_EQUEUE(q) \
+ UWord EQUE_DEF_QUEUE(q)[DEF_EQUEUE_SIZE]; \
+ ErtsEQueue q = { \
+ EQUE_DEF_QUEUE(q), /* start */ \
+ EQUE_DEF_QUEUE(q), /* front */ \
+ EQUE_DEF_QUEUE(q), /* back */ \
+ 1, /* possibly_empty */ \
+ EQUE_DEF_QUEUE(q) + DEF_EQUEUE_SIZE, /* end */ \
+ ERTS_ALC_T_ESTACK /* alloc_type */ \
+ }
+
+#define DESTROY_EQUEUE(q) \
+do { \
+ if (q.start != EQUE_DEF_QUEUE(q)) { \
+ erts_free(q.alloc_type, q.start); \
+ } \
+} while(0)
+
+#define EQUEUE_PUT_UNCHECKED(q, x) \
+do { \
+ q.possibly_empty = 0; \
+ *(q.back) = (x); \
+ if (++(q.back) == q.end) { \
+ q.back = q.start; \
+ } \
+} while(0)
+
+#define EQUEUE_PUT(q, x) \
+do { \
+ if (q.back == q.front && !q.possibly_empty) { \
+ erl_grow_equeue(&q, EQUE_DEF_QUEUE(q)); \
+ } \
+ EQUEUE_PUT_UNCHECKED(q, x); \
+} while(0)
+
+#define EQUEUE_ISEMPTY(q) (q.back == q.front && q.possibly_empty)
+
+ERTS_GLB_INLINE Eterm erts_equeue_get(ErtsEQueue *q);
+
+#if ERTS_GLB_INLINE_INCL_FUNC_DEF
+ERTS_GLB_INLINE Eterm erts_equeue_get(ErtsEQueue *q) {
+ Eterm x;
+ q->possibly_empty = 1;
+ x = *(q->front);
+ if (++(q->front) == q->end) {
+ q->front = q->start;
+ }
+ return x;
+}
+#endif
+#define EQUEUE_GET(q) erts_equeue_get(&(q));
+
/* binary.c */
void erts_emasculate_writable_binary(ProcBin* pb);
@@ -899,6 +987,12 @@ Eterm erl_is_function(Process* p, Eterm arg1, Eterm arg2);
/* beam_bif_load.c */
Eterm erts_check_process_code(Process *c_p, Eterm module, int allow_gc, int *redsp);
+typedef struct {
+ Eterm *ptr;
+ Uint sz;
+} copy_literals_t;
+
+extern copy_literals_t erts_clrange;
/* beam_load.c */
typedef struct {
@@ -953,16 +1047,71 @@ __decl_noreturn void __noreturn erl_exit(int n, char*, ...);
__decl_noreturn void __noreturn erl_exit_flush_async(int n, char*, ...);
void erl_error(char*, va_list);
+/* This controls whether sharing-preserving copy is used by Erlang */
+
+#ifdef SHCOPY
+#define SHCOPY_SEND
+#define SHCOPY_SPAWN
+#endif
+
+/* The persistent state while the sharing-preserving copier works */
+
+typedef struct {
+ Eterm queue_default[DEF_EQUEUE_SIZE];
+ Eterm* queue_start;
+ Eterm* queue_end;
+ ErtsAlcType_t queue_alloc_type;
+ UWord bitstore_default[DEF_WSTACK_SIZE];
+ UWord* bitstore_start;
+ ErtsAlcType_t bitstore_alloc_type;
+ Eterm shtable_default[DEF_ESTACK_SIZE];
+ Eterm* shtable_start;
+ ErtsAlcType_t shtable_alloc_type;
+ Uint literal_size;
+ Eterm *range_ptr;
+ Uint range_sz;
+} erts_shcopy_t;
+
+#define INITIALIZE_SHCOPY(info) \
+do { \
+ info.queue_start = info.queue_default; \
+ info.bitstore_start = info.bitstore_default; \
+ info.shtable_start = info.shtable_default; \
+ info.literal_size = 0; \
+ info.range_ptr = erts_clrange.ptr; \
+ info.range_sz = erts_clrange.sz; \
+} while(0)
+
+#define DESTROY_SHCOPY(info) \
+do { \
+ if (info.queue_start != info.queue_default) { \
+ erts_free(info.queue_alloc_type, info.queue_start); \
+ } \
+ if (info.bitstore_start != info.bitstore_default) { \
+ erts_free(info.bitstore_alloc_type, info.bitstore_start); \
+ } \
+ if (info.shtable_start != info.shtable_default) { \
+ erts_free(info.shtable_alloc_type, info.shtable_start); \
+ } \
+} while(0)
+
/* copy.c */
Eterm copy_object_x(Eterm, Process*, Uint);
#define copy_object(Term, Proc) copy_object_x(Term,Proc,0)
Uint size_object(Eterm);
-Eterm copy_struct(Eterm, Uint, Eterm**, ErlOffHeap*);
+Uint copy_shared_calculate(Eterm, erts_shcopy_t*);
+Eterm copy_shared_perform(Eterm, Uint, erts_shcopy_t*, Eterm**, ErlOffHeap*);
+
+Uint size_shared(Eterm);
+
+Eterm copy_struct_x(Eterm, Uint, Eterm**, ErlOffHeap*, Uint* bsz);
+#define copy_struct(Obj,Sz,HPP,OH) \
+ copy_struct_x(Obj,Sz,HPP,OH,NULL)
Eterm copy_shallow(Eterm*, Uint, Eterm**, ErlOffHeap*);
-void move_multi_frags(Eterm** hpp, ErlOffHeap*, ErlHeapFragment* first,
- Eterm* refs, unsigned nrefs);
+void erts_move_multi_frags(Eterm** hpp, ErlOffHeap*, ErlHeapFragment* first,
+ Eterm* refs, unsigned nrefs, int literals);
/* Utilities */
extern void erts_delete_nodes_monitors(Process *, ErtsProcLocks);
@@ -1274,6 +1423,27 @@ int erts_print_system_version(int to, void *arg, Process *c_p);
int erts_hibernate(Process* c_p, Eterm module, Eterm function, Eterm args, Eterm* reg);
+ERTS_GLB_FORCE_INLINE int erts_is_literal(Eterm tptr, Eterm *ptr);
+
+#if ERTS_GLB_INLINE_INCL_FUNC_DEF
+
+ERTS_GLB_FORCE_INLINE int erts_is_literal(Eterm tptr, Eterm *ptr)
+{
+ ASSERT(is_boxed(tptr) || is_list(tptr));
+ ASSERT(ptr == ptr_val(tptr));
+
+#if defined(ERTS_HAVE_IS_IN_LITERAL_RANGE)
+ return erts_is_in_literal_range(ptr);
+#elif defined(TAG_LITERAL_PTR)
+ return is_literal_ptr(tptr);
+#else
+# error Not able to detect literals...
+#endif
+
+}
+
+#endif
+
/*
** Call_trace uses this API for the parameter matching functions
*/
@@ -1327,124 +1497,6 @@ extern erts_driver_t fd_driver;
int erts_beam_jump_table(void);
-/* Should maybe be placed in erl_message.h, but then we get an include mess. */
-ERTS_GLB_INLINE Eterm *
-erts_alloc_message_heap_state(Uint size,
- ErlHeapFragment **bpp,
- ErlOffHeap **ohpp,
- Process *receiver,
- ErtsProcLocks *receiver_locks,
- erts_aint32_t *statep);
-
-ERTS_GLB_INLINE Eterm *
-erts_alloc_message_heap(Uint size,
- ErlHeapFragment **bpp,
- ErlOffHeap **ohpp,
- Process *receiver,
- ErtsProcLocks *receiver_locks);
-
-#if ERTS_GLB_INLINE_INCL_FUNC_DEF
-
-/*
- * NOTE: erts_alloc_message_heap() releases msg q and status
- * lock on receiver without ensuring that other locks are
- * held. User is responsible to ensure that the receiver
- * pointer cannot become invalid until after message has
- * been passed. This is normal done either by increasing
- * reference count on process (preferred) or by holding
- * main or link lock over the whole message passing
- * operation.
- */
-
-ERTS_GLB_INLINE Eterm *
-erts_alloc_message_heap_state(Uint size,
- ErlHeapFragment **bpp,
- ErlOffHeap **ohpp,
- Process *receiver,
- ErtsProcLocks *receiver_locks,
- erts_aint32_t *statep)
-{
- Eterm *hp;
- erts_aint32_t state;
-#ifdef ERTS_SMP
- int locked_main = 0;
- state = erts_smp_atomic32_read_acqb(&receiver->state);
- if (statep)
- *statep = state;
- if (state & (ERTS_PSFLG_EXITING
- | ERTS_PSFLG_PENDING_EXIT))
- goto allocate_in_mbuf;
-#endif
-
- if (size > (Uint) INT_MAX)
- erl_exit(ERTS_ABORT_EXIT, "HUGE size (%beu)\n", size);
-
- if (
-#if defined(ERTS_SMP)
- *receiver_locks & ERTS_PROC_LOCK_MAIN
-#else
- 1
-#endif
- ) {
-#ifdef ERTS_SMP
- try_allocate_on_heap:
-#endif
- state = erts_smp_atomic32_read_nob(&receiver->state);
- if (statep)
- *statep = state;
- if ((state & (ERTS_PSFLG_EXITING
- | ERTS_PSFLG_PENDING_EXIT))
- || (receiver->flags & F_DISABLE_GC)
- || HEAP_LIMIT(receiver) - HEAP_TOP(receiver) <= size) {
- /*
- * The heap is either potentially in an inconsistent
- * state, or not large enough.
- */
-#ifdef ERTS_SMP
- if (locked_main) {
- *receiver_locks &= ~ERTS_PROC_LOCK_MAIN;
- erts_smp_proc_unlock(receiver, ERTS_PROC_LOCK_MAIN);
- }
-#endif
- goto allocate_in_mbuf;
- }
- hp = HEAP_TOP(receiver);
- HEAP_TOP(receiver) = hp + size;
- *bpp = NULL;
- *ohpp = &MSO(receiver);
- }
-#ifdef ERTS_SMP
- else if (erts_smp_proc_trylock(receiver, ERTS_PROC_LOCK_MAIN) == 0) {
- locked_main = 1;
- *receiver_locks |= ERTS_PROC_LOCK_MAIN;
- goto try_allocate_on_heap;
- }
-#endif
- else {
- ErlHeapFragment *bp;
- allocate_in_mbuf:
- bp = new_message_buffer(size);
- hp = bp->mem;
- *bpp = bp;
- *ohpp = &bp->off_heap;
- }
-
- return hp;
-}
-
-ERTS_GLB_INLINE Eterm *
-erts_alloc_message_heap(Uint size,
- ErlHeapFragment **bpp,
- ErlOffHeap **ohpp,
- Process *receiver,
- ErtsProcLocks *receiver_locks)
-{
- return erts_alloc_message_heap_state(size, bpp, ohpp, receiver,
- receiver_locks, NULL);
-}
-
-#endif /* #if ERTS_GLB_INLINE_INCL_FUNC_DEF */
-
#define DeclareTmpHeap(VariableName,Size,Process) \
Eterm VariableName[Size]
#define DeclareTypedTmpHeap(Type,VariableName,Process) \
@@ -1502,6 +1554,7 @@ dtrace_fun_decode(Process *process,
erts_snprintf(mfa_buf, DTRACE_TERM_BUF_SIZE, "%T:%T/%d",
module, function, arity);
}
+
#endif /* #if ERTS_GLB_INLINE_INCL_FUNC_DEF */
#endif /* !__GLOBAL_H__ */
diff --git a/erts/emulator/beam/hash.c b/erts/emulator/beam/hash.c
index acdec28e19..5a0b93f693 100644
--- a/erts/emulator/beam/hash.c
+++ b/erts/emulator/beam/hash.c
@@ -27,8 +27,6 @@
#endif
#include "sys.h"
-#include "erl_vm.h"
-#include "global.h"
#include "hash.h"
/*
@@ -66,6 +64,7 @@ void hash_get_info(HashInfo *hi, Hash *h)
int i;
int max_depth = 0;
int objects = 0;
+ int used = 0;
for (i = 0; i < size; i++) {
int depth = 0;
@@ -76,14 +75,18 @@ void hash_get_info(HashInfo *hi, Hash *h)
depth++;
b = b->next;
}
- if (depth > max_depth)
- max_depth = depth;
+ if (depth) {
+ used++;
+ if (depth > max_depth)
+ max_depth = depth;
+ }
}
+ ASSERT(objects == h->nobjs);
hi->name = h->name;
hi->size = h->size;
- hi->used = h->used;
- hi->objs = objects;
+ hi->used = used;
+ hi->objs = h->nobjs;
hi->depth = max_depth;
}
@@ -119,6 +122,15 @@ hash_table_sz(Hash *h)
}
+static ERTS_INLINE void set_thresholds(Hash* h)
+{
+ h->grow_threshold = (8*h->size)/5; /* grow at 160% load */
+ if (h->size_ix > h->min_size_ix)
+ h->shrink_threshold = h->size / 5; /* shrink at 20% load */
+ else
+ h->shrink_threshold = -1; /* never shrink below inital size */
+}
+
/*
** init a pre allocated or static hash structure
** and allocate buckets.
@@ -145,10 +157,10 @@ Hash* hash_init(int type, Hash* h, char* name, int size, HashFunctions fun)
h->name = name;
h->fun = fun;
h->size = size;
- h->size20percent = h->size/5;
- h->size80percent = (4*h->size)/5;
- h->ix = ix;
- h->used = 0;
+ h->size_ix = ix;
+ h->min_size_ix = ix;
+ h->nobjs = 0;
+ set_thresholds(h);
return h;
}
@@ -199,32 +211,26 @@ static void rehash(Hash* h, int grow)
int i;
if (grow) {
- if ((h_size_table[h->ix+1]) == -1)
+ if ((h_size_table[h->size_ix+1]) == -1)
return;
- h->ix++;
+ h->size_ix++;
}
else {
- if (h->ix == 0)
+ if (h->size_ix == 0)
return;
- h->ix--;
+ h->size_ix--;
}
- h->size = h_size_table[h->ix];
- h->size20percent = h->size/5;
- h->size80percent = (4*h->size)/5;
+ h->size = h_size_table[h->size_ix];
sz = h->size*sizeof(HashBucket*);
new_bucket = (HashBucket **) h->fun.meta_alloc(h->meta_alloc_type, sz);
sys_memzero(new_bucket, sz);
- h->used = 0;
-
for (i = 0; i < old_size; i++) {
HashBucket* b = h->bucket[i];
while (b != (HashBucket*) 0) {
HashBucket* b_next = b->next;
int ix = b->hvalue % h->size;
- if (new_bucket[ix] == NULL)
- h->used++;
b->next = new_bucket[ix];
new_bucket[ix] = b;
b = b_next;
@@ -232,6 +238,7 @@ static void rehash(Hash* h, int grow)
}
h->fun.meta_free(h->meta_alloc_type, (void *) h->bucket);
h->bucket = new_bucket;
+ set_thresholds(h);
}
/*
@@ -268,68 +275,15 @@ void* hash_put(Hash* h, void* tmpl)
}
b = (HashBucket*) h->fun.alloc(tmpl);
- if (h->bucket[ix] == NULL)
- h->used++;
-
b->hvalue = hval;
b->next = h->bucket[ix];
h->bucket[ix] = b;
- if (h->used > h->size80percent) /* rehash at 80% */
+ if (++h->nobjs > h->grow_threshold)
rehash(h, 1);
return (void*) b;
}
-static void
-hash_insert_entry(Hash* h, HashBucket* entry)
-{
- HashValue hval = entry->hvalue;
- int ix = hval % h->size;
- HashBucket* b = h->bucket[ix];
-
- while (b != (HashBucket*) 0) {
- if ((b->hvalue == hval) && (h->fun.cmp((void*)entry, (void*)b) == 0)) {
- abort(); /* Should not happen */
- }
- b = b->next;
- }
-
- if (h->bucket[ix] == NULL)
- h->used++;
-
- entry->next = h->bucket[ix];
- h->bucket[ix] = entry;
-
- if (h->used > h->size80percent) /* rehash at 80% */
- rehash(h, 1);
-}
-
-
-/*
- * Move all entries in src into dst; empty src.
- * Entries in src must not exist in dst.
- */
-void
-erts_hash_merge(Hash* src, Hash* dst)
-{
- int limit = src->size;
- HashBucket** bucket = src->bucket;
- int i;
-
- src->used = 0;
- for (i = 0; i < limit; i++) {
- HashBucket* b = bucket[i];
- HashBucket* next;
-
- bucket[i] = NULL;
- while (b) {
- next = b->next;
- hash_insert_entry(dst, b);
- b = next;
- }
- }
-}
-
/*
** Erase hash entry return template if erased
** return 0 if not erased
@@ -348,9 +302,7 @@ void* hash_erase(Hash* h, void* tmpl)
else
h->bucket[ix] = b->next;
h->fun.free((void*)b);
- if (h->bucket[ix] == NULL)
- h->used--;
- if (h->used < h->size20percent) /* rehash at 20% */
+ if (--h->nobjs < h->shrink_threshold)
rehash(h, 0);
return tmpl;
}
@@ -381,9 +333,7 @@ hash_remove(Hash *h, void *tmpl)
prev->next = b->next;
else
h->bucket[ix] = b->next;
- if (h->bucket[ix] == NULL)
- h->used--;
- if (h->used < h->size20percent) /* rehash at 20% */
+ if (--h->nobjs < h->shrink_threshold)
rehash(h, 0);
return (void *) b;
}
diff --git a/erts/emulator/beam/hash.h b/erts/emulator/beam/hash.h
index e98f6c32e1..e94aaa0a84 100644
--- a/erts/emulator/beam/hash.h
+++ b/erts/emulator/beam/hash.h
@@ -78,10 +78,11 @@ struct hash
int meta_alloc_type; /* argument to pass to meta_alloc and meta_free */
char* name; /* Table name (static string, for debugging) */
int size; /* Number of slots */
- int size20percent; /* 20 percent of number of slots */
- int size80percent; /* 80 percent of number of slots */
- int ix; /* Size index in size table */
- int used; /* Number of slots used */
+ int shrink_threshold;
+ int grow_threshold;
+ int size_ix; /* Size index in size table */
+ int min_size_ix; /* Never shrink table smaller than this */
+ int nobjs; /* Number of objects in table */
HashBucket** bucket; /* Vector of bucket pointers (objects) */
};
@@ -99,6 +100,4 @@ void* hash_erase(Hash*, void*);
void* hash_remove(Hash*, void*);
void hash_foreach(Hash*, void (*func)(void *, void *), void *);
-void erts_hash_merge(Hash* src, Hash* dst);
-
#endif
diff --git a/erts/emulator/beam/io.c b/erts/emulator/beam/io.c
index 8d9199162c..93c591b124 100644
--- a/erts/emulator/beam/io.c
+++ b/erts/emulator/beam/io.c
@@ -1430,7 +1430,7 @@ queue_port_sched_op_reply(Process *rp,
erts_factory_trim_and_close(factory, &msg, 1);
- erts_queue_message(rp, rp_locksp, factory->heap_frags, msg, NIL);
+ erts_queue_message(rp, rp_locksp, factory->message, msg, NIL);
}
static void
@@ -1438,12 +1438,9 @@ port_sched_op_reply(Eterm to, Uint32 *ref_num, Eterm msg)
{
Process *rp = erts_proc_lookup_raw(to);
if (rp) {
- ErlOffHeap *ohp;
- ErlHeapFragment* bp;
ErtsHeapFactory factory;
Eterm msg_copy;
Uint hsz, msg_sz;
- Eterm *hp;
ErtsProcLocks rp_locks = 0;
hsz = ERTS_QUEUE_PORT_SCHED_OP_REPLY_SIZE;
@@ -1454,18 +1451,13 @@ port_sched_op_reply(Eterm to, Uint32 *ref_num, Eterm msg)
hsz += msg_sz;
}
- hp = erts_alloc_message_heap(hsz,
- &bp,
- &ohp,
- rp,
- &rp_locks);
- erts_factory_message_init(&factory, rp, hp, bp);
- if (is_immed(msg))
- msg_copy = msg;
- else {
- msg_copy = copy_struct(msg, msg_sz, &hp, ohp);
- factory.hp = hp;
- }
+ (void) erts_factory_message_create(&factory, rp,
+ &rp_locks, hsz);
+ msg_copy = (is_immed(msg)
+ ? msg
+ : copy_struct(msg, msg_sz,
+ &factory.hp,
+ factory.off_heap));
queue_port_sched_op_reply(rp,
&rp_locks,
@@ -3167,16 +3159,17 @@ deliver_result(Eterm sender, Eterm pid, Eterm res)
if (rp) {
Eterm tuple;
- ErlHeapFragment *bp;
+ ErtsMessage *mp;
ErlOffHeap *ohp;
Eterm* hp;
Uint sz_res;
sz_res = size_object(res);
- hp = erts_alloc_message_heap(sz_res + 3, &bp, &ohp, rp, &rp_locks);
+ mp = erts_alloc_message_heap(rp, &rp_locks,
+ sz_res + 3, &hp, &ohp);
res = copy_struct(res, sz_res, &hp, ohp);
tuple = TUPLE2(hp, sender, res);
- erts_queue_message(rp, &rp_locks, bp, tuple, NIL);
+ erts_queue_message(rp, &rp_locks, mp, tuple, NIL);
if (rp_locks)
erts_smp_proc_unlock(rp, rp_locks);
@@ -3204,7 +3197,7 @@ static void deliver_read_message(Port* prt, erts_aint32_t state, Eterm to,
Eterm tuple;
Process* rp;
Eterm* hp;
- ErlHeapFragment *bp;
+ ErtsMessage *mp;
ErlOffHeap *ohp;
ErtsProcLocks rp_locks = 0;
int scheduler = erts_get_scheduler_id() != 0;
@@ -3230,7 +3223,7 @@ static void deliver_read_message(Port* prt, erts_aint32_t state, Eterm to,
if (!rp)
return;
- hp = erts_alloc_message_heap(need, &bp, &ohp, rp, &rp_locks);
+ mp = erts_alloc_message_heap(rp, &rp_locks, need, &hp, &ohp);
listp = NIL;
if ((state & ERTS_PORT_SFLG_BINARY_IO) == 0) {
@@ -3272,7 +3265,7 @@ static void deliver_read_message(Port* prt, erts_aint32_t state, Eterm to,
tuple = TUPLE2(hp, prt->common.id, tuple);
hp += 3;
- erts_queue_message(rp, &rp_locks, bp, tuple, am_undefined);
+ erts_queue_message(rp, &rp_locks, mp, tuple, am_undefined);
if (rp_locks)
erts_smp_proc_unlock(rp, rp_locks);
if (!scheduler)
@@ -3346,7 +3339,7 @@ deliver_vec_message(Port* prt, /* Port */
Eterm tuple;
Process* rp;
Eterm* hp;
- ErlHeapFragment *bp;
+ ErtsMessage *mp;
ErlOffHeap *ohp;
ErtsProcLocks rp_locks = 0;
int scheduler = erts_get_scheduler_id() != 0;
@@ -3378,7 +3371,7 @@ deliver_vec_message(Port* prt, /* Port */
need += (hlen+csize)*2;
}
- hp = erts_alloc_message_heap(need, &bp, &ohp, rp, &rp_locks);
+ mp = erts_alloc_message_heap(rp, &rp_locks, need, &hp, &ohp);
listp = NIL;
iov += vsize;
@@ -3439,7 +3432,7 @@ deliver_vec_message(Port* prt, /* Port */
tuple = TUPLE2(hp, prt->common.id, tuple);
hp += 3;
- erts_queue_message(rp, &rp_locks, bp, tuple, am_undefined);
+ erts_queue_message(rp, &rp_locks, mp, tuple, am_undefined);
erts_smp_proc_unlock(rp, rp_locks);
if (!scheduler)
erts_proc_dec_refc(rp);
@@ -3930,7 +3923,6 @@ write_port_control_result(int control_flags,
ErlDrvSizeT resp_size,
char *pre_alloc_buf,
Eterm **hpp,
- ErlHeapFragment *bp,
ErlOffHeap *ohp)
{
Eterm res;
@@ -4004,9 +3996,6 @@ port_sig_control(Port *prt,
if (res == ERTS_PORT_OP_DONE) {
Eterm msg;
- Eterm *hp;
- ErlHeapFragment *bp;
- ErlOffHeap *ohp;
ErtsHeapFactory factory;
Process *rp;
ErtsProcLocks rp_locks = 0;
@@ -4026,22 +4015,15 @@ port_sig_control(Port *prt,
hsz = rsz + ERTS_QUEUE_PORT_SCHED_OP_REPLY_SIZE;
- hp = erts_alloc_message_heap(hsz,
- &bp,
- &ohp,
- rp,
- &rp_locks);
- erts_factory_message_init(&factory, rp, hp, bp);
+ (void) erts_factory_message_create(&factory, rp,
+ &rp_locks, hsz);
msg = write_port_control_result(control_flags,
resp_bufp,
resp_size,
&resp_buf[0],
- &hp,
- bp,
- ohp);
- factory.hp = hp;
-
+ &factory.hp,
+ factory.off_heap);
queue_port_sched_op_reply(rp,
&rp_locks,
&factory,
@@ -4200,7 +4182,6 @@ erts_port_control(Process* c_p,
resp_size,
&resp_buf[0],
&hp,
- NULL,
&c_p->off_heap);
BUMP_REDS(c_p, ERTS_PORT_REDS_CONTROL);
return ERTS_PORT_OP_DONE;
@@ -4359,21 +4340,14 @@ port_sig_call(Port *prt,
hsz = erts_decode_ext_size((byte *) resp_bufp, resp_size);
if (hsz >= 0) {
- ErlHeapFragment* bp;
- ErlOffHeap* ohp;
ErtsHeapFactory factory;
byte *endp;
hsz += 3; /* ok tuple */
hsz += ERTS_QUEUE_PORT_SCHED_OP_REPLY_SIZE;
- hp = erts_alloc_message_heap(hsz,
- &bp,
- &ohp,
- rp,
- &rp_locks);
+ (void) erts_factory_message_create(&factory, rp, &rp_locks, hsz);
endp = (byte *) resp_bufp;
- erts_factory_message_init(&factory, rp, hp, bp);
msg = erts_decode_ext(&factory, &endp);
if (is_value(msg)) {
hp = erts_produce_heap(&factory,
@@ -4634,7 +4608,9 @@ port_sig_info(Port *prt,
sigdp->u.info.item);
if (is_value(value)) {
ErtsHeapFactory factory;
- erts_factory_message_init(&factory, NULL, hp, bp);
+ ErtsMessage *mp = erts_alloc_message(0, NULL);
+ mp->data.heap_frag = bp;
+ erts_factory_selfcontained_message_init(&factory, mp, hp);
queue_port_sched_op_reply(rp,
&rp_locks,
&factory,
@@ -4722,8 +4698,8 @@ reply_io_bytes(void *vreq)
rp = erts_proc_lookup(req->pid);
if (rp) {
- ErlOffHeap *ohp = NULL;
- ErlHeapFragment *bp = NULL;
+ ErlOffHeap *ohp;
+ ErtsMessage *mp;
ErtsProcLocks rp_locks;
Eterm ref, msg, ein, eout, *hp;
Uint64 in, out;
@@ -4745,7 +4721,7 @@ reply_io_bytes(void *vreq)
erts_bld_uint64(NULL, &hsz, in);
erts_bld_uint64(NULL, &hsz, out);
- hp = erts_alloc_message_heap(hsz, &bp, &ohp, rp, &rp_locks);
+ mp = erts_alloc_message_heap(rp, &rp_locks, hsz, &hp, &ohp);
ref = make_internal_ref(hp);
write_ref_thing(hp, req->refn[0], req->refn[1], req->refn[2]);
@@ -4755,7 +4731,7 @@ reply_io_bytes(void *vreq)
eout = erts_bld_uint64(&hp, NULL, out);
msg = TUPLE4(hp, ref, make_small(sched_id), ein, eout);
- erts_queue_message(rp, &rp_locks, bp, msg, NIL);
+ erts_queue_message(rp, &rp_locks, mp, msg, NIL);
if (req->sched_id == sched_id)
rp_locks &= ~ERTS_PROC_LOCK_MAIN;
@@ -5204,11 +5180,11 @@ ErlDrvTermData driver_mk_term_nil(void)
void driver_report_exit(ErlDrvPort ix, int status)
{
Eterm* hp;
+ ErlOffHeap *ohp;
Eterm tuple;
Process *rp;
Eterm pid;
- ErlHeapFragment *bp = NULL;
- ErlOffHeap *ohp;
+ ErtsMessage *mp;
ErtsProcLocks rp_locks = 0;
int scheduler = erts_get_scheduler_id() != 0;
Port* prt = erts_drvport2port(ix);
@@ -5228,13 +5204,13 @@ void driver_report_exit(ErlDrvPort ix, int status)
if (!rp)
return;
- hp = erts_alloc_message_heap(3+3, &bp, &ohp, rp, &rp_locks);
+ mp = erts_alloc_message_heap(rp, &rp_locks, 3+3, &hp, &ohp);
tuple = TUPLE2(hp, am_exit_status, make_small(status));
hp += 3;
tuple = TUPLE2(hp, prt->common.id, tuple);
- erts_queue_message(rp, &rp_locks, bp, tuple, am_undefined);
+ erts_queue_message(rp, &rp_locks, mp, tuple, am_undefined);
erts_smp_proc_unlock(rp, rp_locks);
if (!scheduler)
@@ -5344,7 +5320,6 @@ driver_deliver_term(Eterm to, ErlDrvTermData* data, int len)
ErtsProcLocks rp_locks = 0;
struct b2t_states__ b2t;
int scheduler;
- int is_heap_need_limited = 1;
ErtsSchedulerData *esdp = erts_get_scheduler_data();
ERTS_UNDEF(mess,NIL);
@@ -5513,9 +5488,6 @@ driver_deliver_term(Eterm to, ErlDrvTermData* data, int len)
need += hsz;
ptr += 2;
depth++;
- if (size > MAP_SMALL_MAP_LIMIT*3) { /* may contain big map */
- is_heap_need_limited = 0;
- }
break;
}
case ERL_DRV_MAP: { /* int */
@@ -5523,7 +5495,6 @@ driver_deliver_term(Eterm to, ErlDrvTermData* data, int len)
if ((int) ptr[0] < 0) ERTS_DDT_FAIL;
if (ptr[0] > MAP_SMALL_MAP_LIMIT) {
need += HASHMAP_ESTIMATED_HEAP_SIZE(ptr[0]);
- is_heap_need_limited = 0;
} else {
need += MAP_HEADER_FLATMAP_SZ + 1 + 2*ptr[0];
}
@@ -5562,17 +5533,7 @@ driver_deliver_term(Eterm to, ErlDrvTermData* data, int len)
goto done;
}
- /* Try copy directly to destination heap if we know there are no big maps */
- if (is_heap_need_limited) {
- ErlOffHeap *ohp;
- ErlHeapFragment* bp;
- Eterm* hp = erts_alloc_message_heap(need, &bp, &ohp, rp, &rp_locks);
- erts_factory_message_init(&factory, rp, hp, bp);
- }
- else {
- erts_factory_message_init(&factory, NULL, NULL,
- new_message_buffer(need));
- }
+ (void) erts_factory_message_create(&factory, rp, &rp_locks, need);
/*
* Interpret the instructions and build the term.
@@ -5841,9 +5802,9 @@ driver_deliver_term(Eterm to, ErlDrvTermData* data, int len)
if (res > 0) {
mess = ESTACK_POP(stack); /* get resulting value */
- erts_factory_close(&factory);
+ erts_factory_trim_and_close(&factory, &mess, 1);
/* send message */
- erts_queue_message(rp, &rp_locks, factory.heap_frags, mess, am_undefined);
+ erts_queue_message(rp, &rp_locks, factory.message, mess, am_undefined);
}
else {
if (b2t.ix > b2t.used)
@@ -7687,15 +7648,15 @@ int null_func(void)
}
int
-erl_drv_putenv(char *key, char *value)
+erl_drv_putenv(const char *key, char *value)
{
- return erts_sys_putenv_raw(key, value);
+ return erts_sys_putenv_raw((char*)key, value);
}
int
-erl_drv_getenv(char *key, char *value, size_t *value_size)
+erl_drv_getenv(const char *key, char *value, size_t *value_size)
{
- return erts_sys_getenv_raw(key, value, value_size);
+ return erts_sys_getenv_raw((char*)key, value, value_size);
}
/* get heart_port
diff --git a/erts/emulator/beam/module.c b/erts/emulator/beam/module.c
index 2db6f957c6..f5c7b177d3 100644
--- a/erts/emulator/beam/module.c
+++ b/erts/emulator/beam/module.c
@@ -74,8 +74,8 @@ static Module* module_alloc(Module* tmpl)
erts_smp_atomic_add_nob(&tot_module_bytes, sizeof(Module));
obj->module = tmpl->module;
- obj->curr.code = 0;
- obj->old.code = 0;
+ obj->curr.code_hdr = 0;
+ obj->old.code_hdr = 0;
obj->curr.code_length = 0;
obj->old.code_length = 0;
obj->slot.index = -1;
diff --git a/erts/emulator/beam/module.h b/erts/emulator/beam/module.h
index c8a6351b04..e66d628ca9 100644
--- a/erts/emulator/beam/module.h
+++ b/erts/emulator/beam/module.h
@@ -26,7 +26,7 @@
#endif
struct erl_module_instance {
- BeamInstr* code;
+ BeamCodeHeader* code_hdr;
int code_length; /* Length of loaded code in bytes. */
unsigned catches;
struct erl_module_nif* nif;
diff --git a/erts/emulator/beam/ops.tab b/erts/emulator/beam/ops.tab
index 46fefb88af..081c4108a0 100644
--- a/erts/emulator/beam/ops.tab
+++ b/erts/emulator/beam/ops.tab
@@ -1036,7 +1036,7 @@ call_bif e
bif0 u$bif:erlang:self/0 Dst=d => self Dst
bif0 u$bif:erlang:node/0 Dst=d => node Dst
-bif1 Fail Bif=u$bif:erlang:get/1 Src=s Dst=d => i_get Src Dst
+bif1 Fail Bif=u$bif:erlang:get/1 Src=s Dst=d => gen_get(Src, Dst)
bif2 Jump=j u$bif:erlang:element/2 S1=s S2=xy Dst=d => gen_element(Jump, S1, S2, Dst)
@@ -1045,6 +1045,7 @@ bif1 p Bif S1 Dst => bif1_body Bif S1 Dst
bif2 p Bif S1 S2 Dst => i_bif2_body Bif S1 S2 Dst
bif2 Fail Bif S1 S2 Dst => i_bif2 Fail Bif S1 S2 Dst
+i_get_hash c I d
i_get s d
%macro: self Self
diff --git a/erts/emulator/beam/sys.h b/erts/emulator/beam/sys.h
index 522d899c94..53f8313daa 100644
--- a/erts/emulator/beam/sys.h
+++ b/erts/emulator/beam/sys.h
@@ -21,6 +21,19 @@
#ifndef __SYS_H__
#define __SYS_H__
+#if !defined(__GNUC__)
+# define ERTS_AT_LEAST_GCC_VSN__(MAJ, MIN, PL) 0
+#elif !defined(__GNUC_MINOR__)
+# define ERTS_AT_LEAST_GCC_VSN__(MAJ, MIN, PL) \
+ ((__GNUC__ << 24) >= (((MAJ) << 24) | ((MIN) << 12) | (PL)))
+#elif !defined(__GNUC_PATCHLEVEL__)
+# define ERTS_AT_LEAST_GCC_VSN__(MAJ, MIN, PL) \
+ (((__GNUC__ << 24) | (__GNUC_MINOR__ << 12)) >= (((MAJ) << 24) | ((MIN) << 12) | (PL)))
+#else
+# define ERTS_AT_LEAST_GCC_VSN__(MAJ, MIN, PL) \
+ (((__GNUC__ << 24) | (__GNUC_MINOR__ << 12) | __GNUC_PATCHLEVEL__) >= (((MAJ) << 24) | ((MIN) << 12) | (PL)))
+#endif
+
#ifdef ERTS_INLINE
# ifndef ERTS_CAN_INLINE
# define ERTS_CAN_INLINE 1
@@ -38,6 +51,17 @@
# endif
#endif
+#ifndef ERTS_FORCE_INLINE
+# if ERTS_AT_LEAST_GCC_VSN__(3,1,1)
+# define ERTS_FORCE_INLINE __inline__ __attribute__((__always_inline__))
+# elif defined(__WIN32__)
+# define ERTS_FORCE_INLINE __forceinline
+# endif
+# ifndef ERTS_FORCE_INLINE
+# define ERTS_FORCE_INLINE ERTS_INLINE
+# endif
+#endif
+
#if defined(DEBUG) || defined(ERTS_ENABLE_LOCK_CHECK)
# undef ERTS_CAN_INLINE
# define ERTS_CAN_INLINE 0
@@ -46,8 +70,10 @@
#endif
#if ERTS_CAN_INLINE
+#define ERTS_GLB_FORCE_INLINE static ERTS_FORCE_INLINE
#define ERTS_GLB_INLINE static ERTS_INLINE
#else
+#define ERTS_GLB_FORCE_INLINE
#define ERTS_GLB_INLINE
#endif
@@ -63,6 +89,9 @@
#define ERTS_I64_LITERAL(X) X##LL
+#define ErtsInArea(ptr,start,nbytes) \
+ ((UWord)((char*)(ptr) - (char*)(start)) < (nbytes))
+
#if defined (__WIN32__)
# include "erl_win_sys.h"
#else
@@ -100,19 +129,6 @@ typedef int ErtsSysFdType;
typedef ERTS_SYS_FD_TYPE ErtsSysFdType;
#endif
-#if !defined(__GNUC__)
-# define ERTS_AT_LEAST_GCC_VSN__(MAJ, MIN, PL) 0
-#elif !defined(__GNUC_MINOR__)
-# define ERTS_AT_LEAST_GCC_VSN__(MAJ, MIN, PL) \
- ((__GNUC__ << 24) >= (((MAJ) << 24) | ((MIN) << 12) | (PL)))
-#elif !defined(__GNUC_PATCHLEVEL__)
-# define ERTS_AT_LEAST_GCC_VSN__(MAJ, MIN, PL) \
- (((__GNUC__ << 24) | (__GNUC_MINOR__ << 12)) >= (((MAJ) << 24) | ((MIN) << 12) | (PL)))
-#else
-# define ERTS_AT_LEAST_GCC_VSN__(MAJ, MIN, PL) \
- (((__GNUC__ << 24) | (__GNUC_MINOR__ << 12) | __GNUC_PATCHLEVEL__) >= (((MAJ) << 24) | ((MIN) << 12) | (PL)))
-#endif
-
#if ERTS_AT_LEAST_GCC_VSN__(2, 96, 0)
# define ERTS_LIKELY(BOOL) __builtin_expect((BOOL), !0)
# define ERTS_UNLIKELY(BOOL) __builtin_expect((BOOL), 0)
@@ -570,7 +586,6 @@ Uint erts_sys_misc_mem_sz(void);
/* Io constants to erts_print and erts_putc */
#define ERTS_PRINT_STDERR (2)
#define ERTS_PRINT_STDOUT (1)
-#define ERTS_PRINT_INVALID (0) /* Don't want to use 0 since CBUF was 0 */
#define ERTS_PRINT_FILE (-1)
#define ERTS_PRINT_SBUF (-2)
#define ERTS_PRINT_SNBUF (-3)
@@ -1036,7 +1051,6 @@ extern int erts_use_kernel_poll;
#define put_int8(i, s) do {((unsigned char*)(s))[0] = (i) & 0xff;} while (0)
-
/*
* Use DEBUGF as you would use printf, but use double parentheses:
*
diff --git a/erts/emulator/beam/utils.c b/erts/emulator/beam/utils.c
index 5fe4091adc..ef851d840d 100644
--- a/erts/emulator/beam/utils.c
+++ b/erts/emulator/beam/utils.c
@@ -110,7 +110,6 @@ Eterm*
erts_heap_alloc(Process* p, Uint need, Uint xtra)
{
ErlHeapFragment* bp;
- Eterm* htop;
Uint n;
#if defined(DEBUG) || defined(CHECK_FOR_HOLES)
Uint i;
@@ -156,16 +155,6 @@ erts_heap_alloc(Process* p, Uint need, Uint xtra)
n--;
#endif
- /*
- * When we have created a heap fragment, we are no longer allowed
- * to store anything more on the heap.
- */
- htop = HEAP_TOP(p);
- if (htop < HEAP_LIMIT(p)) {
- *htop = make_pos_bignum_header(HEAP_LIMIT(p)-htop-1);
- HEAP_TOP(p) = HEAP_LIMIT(p);
- }
-
bp->next = MBUF(p);
MBUF(p) = bp;
bp->alloc_size = n;
@@ -269,6 +258,31 @@ erl_grow_pstack(ErtsPStack* s, void* default_pstack, unsigned need_bytes)
s->psp = s->pstart + sp_offs;
}
+/*
+ * Helper function for the EQUEUE macros defined in global.h.
+ */
+
+void
+erl_grow_equeue(ErtsEQueue* q, Eterm* default_equeue)
+{
+ Uint old_size = (q->end - q->start);
+ Uint new_size = old_size * 2;
+ Uint first_part = (q->end - q->front);
+ Uint second_part = (q->back - q->start);
+ Eterm* new_ptr = erts_alloc(q->alloc_type, new_size*sizeof(Eterm));
+ ASSERT(q->back == q->front); // of course the queue is full now!
+ if (first_part > 0)
+ sys_memcpy(new_ptr, q->front, first_part*sizeof(Eterm));
+ if (second_part > 0)
+ sys_memcpy(new_ptr+first_part, q->start, second_part*sizeof(Eterm));
+ if (q->start != default_equeue)
+ erts_free(q->alloc_type, q->start);
+ q->start = new_ptr;
+ q->end = q->start + new_size;
+ q->front = q->start;
+ q->back = q->start + old_size;
+}
+
/* CTYPE macros */
#define LATIN1
@@ -399,9 +413,6 @@ erts_print(int to, void *arg, char *format, ...)
case ERTS_PRINT_DSBUF:
res = erts_vdsprintf((erts_dsprintf_buf_t *) arg, format, arg_list);
break;
- case ERTS_PRINT_INVALID:
- res = -EINVAL;
- break;
default:
res = erts_vfdprintf((int) to, format, arg_list);
break;
@@ -2284,7 +2295,11 @@ static void do_send_logger_message(Eterm *hp, ErlOffHeap *ohp, ErlHeapFragment *
erts_queue_error_logger_message(from, message, bp);
}
#else
- erts_queue_message(p, NULL /* only used for smp build */, bp, message, NIL);
+ {
+ ErtsMessage *mp = erts_alloc_message(0, NULL);
+ mp->data.heap_frag = bp;
+ erts_queue_message(p, NULL /* only used for smp build */, mp, message, NIL);
+ }
#endif
}
diff --git a/erts/emulator/drivers/common/efile_drv.c b/erts/emulator/drivers/common/efile_drv.c
index 2cb4662fc3..a82abc3e9f 100644
--- a/erts/emulator/drivers/common/efile_drv.c
+++ b/erts/emulator/drivers/common/efile_drv.c
@@ -2575,7 +2575,6 @@ file_async_ready(ErlDrvData e, ErlDrvThreadData data)
case FILE_CLOSE_ON_PORT_EXIT:
/* See file_stop. However this is never invoked after the port is killed. */
free_data(data);
- EF_FREE(desc);
desc = NULL;
/* This is it for this port, so just send dtrace and return, avoid doing anything to the freed data */
DTRACE6(efile_drv_return, sched_i1, sched_i2, sched_utag,
diff --git a/erts/emulator/drivers/common/inet_drv.c b/erts/emulator/drivers/common/inet_drv.c
index 1e3360c2b1..e3f5060117 100644
--- a/erts/emulator/drivers/common/inet_drv.c
+++ b/erts/emulator/drivers/common/inet_drv.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1997-2013. All Rights Reserved.
+ * Copyright Ericsson AB 1997-2015. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -5762,9 +5762,9 @@ static int inet_set_opts(inet_descriptor* desc, char* ptr, int len)
int arg_sz;
enum PacketParseType old_htype = desc->htype;
int old_active = desc->active;
- int propagate = 0; /* Set to 1 if failure to set this option
- should be propagated to erlang (not all
- errors can be propagated for BC reasons) */
+ int propagate; /* Set to 1 if failure to set this option
+ should be propagated to erlang (not all
+ errors can be propagated for BC reasons) */
int res;
#ifdef HAVE_SCTP
/* SCTP sockets are treated completely separately: */
@@ -5781,6 +5781,7 @@ static int inet_set_opts(inet_descriptor* desc, char* ptr, int len)
arg_ptr = (char*) &ival;
arg_sz = sizeof(ival);
proto = SOL_SOCKET;
+ propagate = 0;
switch(opt) {
case INET_LOPT_HEADER:
diff --git a/erts/emulator/hipe/hipe_bif0.c b/erts/emulator/hipe/hipe_bif0.c
index 70a57ba465..6f495b8825 100644
--- a/erts/emulator/hipe/hipe_bif0.c
+++ b/erts/emulator/hipe/hipe_bif0.c
@@ -488,7 +488,7 @@ static void *const_term_alloc(void *tmpl)
alloc_size = size + (offsetof(struct const_term, mem)/sizeof(Eterm));
hipe_constants_size += alloc_size;
- p = (struct const_term*)erts_alloc(ERTS_ALC_T_HIPE, alloc_size * sizeof(Eterm));
+ p = (struct const_term*)erts_alloc(ERTS_ALC_T_LITERAL, alloc_size * sizeof(Eterm));
/* I have absolutely no idea if having a private 'off_heap'
works or not. _Some_ off_heap object is required for
@@ -497,6 +497,8 @@ static void *const_term_alloc(void *tmpl)
hp = &p->mem[0];
p->val = copy_struct(obj, size, &hp, &const_term_table_off_heap);
+ erts_set_literal_tag(&p->val, &p->mem[0], size);
+
return &p->bucket;
}
@@ -577,15 +579,15 @@ static void print_mfa(Eterm mod, Eterm fun, unsigned int ari)
static Uint *hipe_find_emu_address(Eterm mod, Eterm name, unsigned int arity)
{
Module *modp;
- Uint *code_base;
+ BeamCodeHeader* code_hdr;
int i, n;
modp = erts_get_module(mod, erts_active_code_ix());
- if (modp == NULL || (code_base = modp->curr.code) == NULL)
+ if (modp == NULL || (code_hdr = modp->curr.code_hdr) == NULL)
return NULL;
- n = code_base[MI_NUM_FUNCTIONS];
+ n = code_hdr->num_functions;
for (i = 0; i < n; ++i) {
- Uint *code_ptr = (Uint*)code_base[MI_FUNCTIONS+i];
+ Uint *code_ptr = (Uint*)code_hdr->functions[i];
ASSERT(code_ptr[0] == BeamOpCode(op_i_func_info_IaaI));
if (code_ptr[3] == name && code_ptr[4] == arity)
return code_ptr+5;
diff --git a/erts/emulator/hipe/hipe_gc.c b/erts/emulator/hipe/hipe_gc.c
index 2c747771ac..2e19bf88bf 100644
--- a/erts/emulator/hipe/hipe_gc.c
+++ b/erts/emulator/hipe/hipe_gc.c
@@ -46,10 +46,6 @@ Eterm *fullsweep_nstack(Process *p, Eterm *n_htop)
/* arch-specific nstack walk state */
struct nstack_walk_state walk_state;
- /* fullsweep-specific state */
- char *src, *oh;
- Uint src_size, oh_size;
-
if (!p->hipe.nstack) {
ASSERT(!p->hipe.nsp && !p->hipe.nstend);
return n_htop;
@@ -66,11 +62,6 @@ Eterm *fullsweep_nstack(Process *p, Eterm *n_htop)
sdesc = nstack_walk_init_sdesc(p, &walk_state);
- src = (char*)HEAP_START(p);
- src_size = (char*)HEAP_TOP(p) - src;
- oh = (char*)OLD_HEAP(p);
- oh_size = (char*)OLD_HTOP(p) - oh;
-
for (;;) {
if (nstack_walk_nsp_reached_end(nsp, nsp_end)) {
if (nsp == nsp_end) {
@@ -97,8 +88,7 @@ Eterm *fullsweep_nstack(Process *p, Eterm *n_htop)
if (IS_MOVED_BOXED(val)) {
ASSERT(is_boxed(val));
*nsp_i = val;
- } else if (in_area(ptr, src, src_size) ||
- in_area(ptr, oh, oh_size)) {
+ } else if (!erts_is_literal(gval, ptr)) {
MOVE_BOXED(ptr, val, n_htop, nsp_i);
}
} else if (is_list(gval)) {
@@ -106,8 +96,7 @@ Eterm *fullsweep_nstack(Process *p, Eterm *n_htop)
Eterm val = *ptr;
if (IS_MOVED_CONS(val)) {
*nsp_i = ptr[1];
- } else if (in_area(ptr, src, src_size) ||
- in_area(ptr, oh, oh_size)) {
+ } else if (!erts_is_literal(gval, ptr)) {
ASSERT(within(ptr, p));
MOVE_CONS(ptr, val, n_htop, nsp_i);
}
@@ -139,11 +128,13 @@ void gensweep_nstack(Process *p, Eterm **ptr_old_htop, Eterm **ptr_n_htop)
unsigned int mask;
/* arch-specific nstack walk state */
struct nstack_walk_state walk_state;
+ char *oh;
+ Uint oh_size;
/* gensweep-specific state */
Eterm *old_htop, *n_htop;
- char *heap;
- Uint heap_size, mature_size;
+ char *mature;
+ Uint mature_size;
if (!p->hipe.nstack) {
ASSERT(!p->hipe.nsp && !p->hipe.nstend);
@@ -168,9 +159,10 @@ void gensweep_nstack(Process *p, Eterm **ptr_old_htop, Eterm **ptr_n_htop)
old_htop = *ptr_old_htop;
n_htop = *ptr_n_htop;
- heap = (char*)HEAP_START(p);
- heap_size = (char*)HEAP_TOP(p) - heap;
- mature_size = (char*)HIGH_WATER(p) - heap;
+ mature = (char *) (p->abandoned_heap ? p->abandoned_heap : p->heap);
+ mature_size = (char*)HIGH_WATER(p) - mature;
+ oh = (char*)OLD_HEAP(p);
+ oh_size = (char*)OLD_HTOP(p) - oh;
for (;;) {
if (nstack_walk_nsp_reached_end(nsp, nsp_end)) {
@@ -209,9 +201,9 @@ void gensweep_nstack(Process *p, Eterm **ptr_old_htop, Eterm **ptr_n_htop)
if (IS_MOVED_BOXED(val)) {
ASSERT(is_boxed(val));
*nsp_i = val;
- } else if (in_area(ptr, heap, mature_size)) {
+ } else if (ErtsInArea(ptr, mature, mature_size)) {
MOVE_BOXED(ptr, val, old_htop, nsp_i);
- } else if (in_area(ptr, heap, heap_size)) {
+ } else if (ErtsInYoungGen(gval, ptr, oh, oh_size)) {
ASSERT(within(ptr, p));
MOVE_BOXED(ptr, val, n_htop, nsp_i);
}
@@ -220,9 +212,9 @@ void gensweep_nstack(Process *p, Eterm **ptr_old_htop, Eterm **ptr_n_htop)
Eterm val = *ptr;
if (IS_MOVED_CONS(val)) {
*nsp_i = ptr[1];
- } else if (in_area(ptr, heap, mature_size)) {
+ } else if (ErtsInArea(ptr, mature, mature_size)) {
MOVE_CONS(ptr, val, old_htop, nsp_i);
- } else if (in_area(ptr, heap, heap_size)) {
+ } else if (ErtsInYoungGen(gval, ptr, oh, oh_size)) {
ASSERT(within(ptr, p));
MOVE_CONS(ptr, val, n_htop, nsp_i);
}
diff --git a/erts/emulator/hipe/hipe_mode_switch.c b/erts/emulator/hipe/hipe_mode_switch.c
index 968452a641..976180cc30 100644
--- a/erts/emulator/hipe/hipe_mode_switch.c
+++ b/erts/emulator/hipe/hipe_mode_switch.c
@@ -196,7 +196,7 @@ hipe_push_beam_trap_frame(Process *p, Eterm reg[], unsigned arity)
ASSERT(!(p->flags & F_DISABLE_GC));
if ((p->stop - 2) < p->htop) {
DPRINTF("calling gc to increase BEAM stack size");
- p->fcalls -= erts_garbage_collect(p, 2, reg, arity);
+ erts_garbage_collect(p, 2, reg, arity);
ASSERT(!((p->stop - 2) < p->htop));
}
p->stop -= 2;
diff --git a/erts/emulator/hipe/hipe_mode_switch.h b/erts/emulator/hipe/hipe_mode_switch.h
index bc863a4f36..620cc6356b 100644
--- a/erts/emulator/hipe/hipe_mode_switch.h
+++ b/erts/emulator/hipe/hipe_mode_switch.h
@@ -95,7 +95,7 @@ ERTS_GLB_INLINE void hipe_reserve_beam_trap_frame(Process *p, Eterm reg[], unsig
/* ensure that at least 2 words are available on the BEAM stack */
if ((p->stop - 2) < p->htop) {
- p->fcalls -= erts_garbage_collect(p, 2, reg, arity);
+ erts_garbage_collect(p, 2, reg, arity);
ASSERT(!((p->stop - 2) < p->htop));
}
p->stop -= 2;
diff --git a/erts/emulator/hipe/hipe_native_bif.c b/erts/emulator/hipe/hipe_native_bif.c
index 688378b2fe..1bfee94e9e 100644
--- a/erts/emulator/hipe/hipe_native_bif.c
+++ b/erts/emulator/hipe/hipe_native_bif.c
@@ -80,7 +80,7 @@ Eterm hipe_show_nstack_1(BIF_ALIST_1)
void hipe_gc(Process *p, Eterm need)
{
hipe_set_narity(p, 1);
- p->fcalls -= erts_garbage_collect(p, unsigned_val(need), NULL, 0);
+ erts_garbage_collect(p, unsigned_val(need), NULL, 0);
hipe_set_narity(p, 0);
}
@@ -157,13 +157,22 @@ BIF_RETTYPE hipe_set_timeout(BIF_ALIST_1)
*/
void hipe_select_msg(Process *p)
{
- ErlMessage *msgp;
+ ErtsMessage *msgp;
msgp = PEEK_MESSAGE(p);
UNLINK_MESSAGE(p, msgp); /* decrements global 'erts_proc_tot_mem' variable */
JOIN_MESSAGE(p);
CANCEL_TIMER(p); /* calls erts_cancel_proc_timer() */
- free_message(msgp);
+ erts_save_message_in_proc(p, msgp);
+ p->flags &= ~F_DELAY_GC;
+ if (ERTS_IS_GC_DESIRED(p)) {
+ /*
+ * We want to GC soon but we leave a few
+ * reductions giving the message some time
+ * to turn into garbage.
+ */
+ ERTS_VBUMP_LEAVE_REDS(p, 5);
+ }
}
void hipe_fclearerror_error(Process *p)
@@ -508,8 +517,9 @@ int hipe_bs_validate_unicode_retract(ErlBinMatchBuffer* mb, Eterm arg)
*/
Eterm hipe_check_get_msg(Process *c_p)
{
- Eterm ret;
- ErlMessage *msgp;
+ ErtsMessage *msgp;
+
+ c_p->flags |= F_DELAY_GC;
next_message:
@@ -531,25 +541,29 @@ Eterm hipe_check_get_msg(Process *c_p)
/* XXX: BEAM doesn't need this */
c_p->hipe_smp.have_receive_locks = 1;
#endif
+ c_p->flags &= ~F_DELAY_GC;
return THE_NON_VALUE;
#ifdef ERTS_SMP
}
#endif
}
- ErtsMoveMsgAttachmentIntoProc(msgp, c_p, c_p->stop, HEAP_TOP(c_p),
- c_p->fcalls, (void) 0, (void) 0);
- ret = ERL_MESSAGE_TERM(msgp);
- if (is_non_value(ret)) {
+
+ if (is_non_value(ERL_MESSAGE_TERM(msgp))
+ && !erts_decode_dist_message(c_p, ERTS_PROC_LOCK_MAIN, msgp, 0)) {
/*
* A corrupt distribution message that we weren't able to decode;
* remove it...
*/
ASSERT(!msgp->data.attached);
UNLINK_MESSAGE(c_p, msgp);
- free_message(msgp);
+ msgp->next = NULL;
+ erts_cleanup_messages(msgp);
goto next_message;
}
- return ret;
+
+ ASSERT(is_value(ERL_MESSAGE_TERM(msgp)));
+
+ return ERL_MESSAGE_TERM(msgp);
}
/*
diff --git a/erts/emulator/hipe/hipe_x86_signal.c b/erts/emulator/hipe/hipe_x86_signal.c
index bb8a3f041f..69d4ea10c2 100644
--- a/erts/emulator/hipe/hipe_x86_signal.c
+++ b/erts/emulator/hipe/hipe_x86_signal.c
@@ -198,7 +198,7 @@ static void do_init(void)
#define INIT() do { if (!init_done()) do_init(); } while (0)
#endif /* __DARWIN__ */
-#if !defined(__GLIBC__) && !defined(__DARWIN__) && !defined(__NetBSD__)
+#if defined(__sun__)
/*
* Assume Solaris/x86 2.8.
* There is a number of sigaction() procedures in libc:
@@ -232,7 +232,34 @@ static void do_init(void)
}
#define _NSIG NSIG
#define INIT() do { if (!init_done()) do_init(); } while (0)
-#endif /* not glibc or darwin */
+#endif /* __sun__ */
+
+#if !(defined(__GLIBC__) || defined(__DARWIN__) || defined(__NetBSD__) || defined(__sun__))
+/*
+ * Unknown libc -- assume musl. Note: musl deliberately does not provide a musl-specific
+ * feature test macro, so we cannot check for it.
+ *
+ * sigaction is a weak alias for __sigaction, which is a wrapper for __libc_sigaction.
+ * There are libc-internal calls to __libc_sigaction which install handlers, so we must
+ * override __libc_sigaction rather than __sigaction.
+ */
+#include <dlfcn.h>
+static int (*__next_sigaction)(int, const struct sigaction*, struct sigaction*);
+#define init_done() (__next_sigaction != 0)
+#define __SIGACTION __libc_sigaction
+static void do_init(void)
+{
+ __next_sigaction = dlsym(RTLD_NEXT, "__libc_sigaction");
+ if (__next_sigaction != 0)
+ return;
+ perror("dlsym");
+ abort();
+}
+#ifndef _NSIG
+#define _NSIG NSIG
+#endif
+#define INIT() do { if (!init_done()) do_init(); } while (0)
+#endif /* !(__GLIBC__ || __DARWIN__ || __NetBSD__ || __sun__) */
#if !defined(__NetBSD__)
/*
diff --git a/erts/emulator/sys/common/erl_mmap.c b/erts/emulator/sys/common/erl_mmap.c
index e6d0e1e281..03ca080c14 100644
--- a/erts/emulator/sys/common/erl_mmap.c
+++ b/erts/emulator/sys/common/erl_mmap.c
@@ -51,23 +51,22 @@
#endif
/*
- * `mmap_state.sa.bot` and `mmap_state.sua.top` are read only after
+ * `mm->sa.bot` and `mm->sua.top` are read only after
* initialization, but the other pointers are not; i.e., only
* ERTS_MMAP_IN_SUPERCARRIER() is allowed without the mutex held.
*/
#define ERTS_MMAP_IN_SUPERCARRIER(PTR) \
- (((UWord) (PTR)) - ((UWord) mmap_state.sa.bot) \
- < ((UWord) mmap_state.sua.top) - ((UWord) mmap_state.sa.bot))
+ (((UWord) (PTR)) - ((UWord) mm->sa.bot) \
+ < ((UWord) mm->sua.top) - ((UWord) mm->sa.bot))
#define ERTS_MMAP_IN_SUPERALIGNED_AREA(PTR) \
- (ERTS_SMP_LC_ASSERT(erts_lc_mtx_is_locked(&mmap_state.mtx)), \
- (((UWord) (PTR)) - ((UWord) mmap_state.sa.bot) \
- < ((UWord) mmap_state.sa.top) - ((UWord) mmap_state.sa.bot)))
+ (ERTS_SMP_LC_ASSERT(erts_lc_mtx_is_locked(&mm->mtx)), \
+ (((UWord) (PTR)) - ((UWord) mm->sa.bot) \
+ < ((UWord) mm->sa.top) - ((UWord) mm->sa.bot)))
#define ERTS_MMAP_IN_SUPERUNALIGNED_AREA(PTR) \
- (ERTS_SMP_LC_ASSERT(erts_lc_mtx_is_locked(&mmap_state.mtx)), \
- (((UWord) (PTR)) - ((UWord) mmap_state.sua.bot) \
- < ((UWord) mmap_state.sua.top) - ((UWord) mmap_state.sua.bot)))
+ (ERTS_SMP_LC_ASSERT(erts_lc_mtx_is_locked(&mm->mtx)), \
+ (((UWord) (PTR)) - ((UWord) mm->sua.bot) \
+ < ((UWord) mm->sua.top) - ((UWord) mm->sua.bot)))
-int erts_have_erts_mmap;
UWord erts_page_inv_mask;
#if defined(DEBUG) || defined(ERTS_MMAP_DEBUG)
@@ -197,10 +196,10 @@ static ErtsMMapOp mmap_ops[ERTS_MMAP_OP_RINGBUF_SZ];
#define ERTS_MMAP_OP_LCK(RES, IN_SZ, OUT_SZ) \
do { \
- erts_smp_mtx_lock(&mmap_state.mtx); \
+ erts_smp_mtx_lock(&mm->mtx); \
ERTS_MMAP_OP_START((IN_SZ)); \
ERTS_MMAP_OP_END((RES), (OUT_SZ)); \
- erts_smp_mtx_unlock(&mmap_state.mtx); \
+ erts_smp_mtx_unlock(&mm->mtx); \
} while (0)
#define ERTS_MUNMAP_OP(PTR, SZ) \
@@ -219,9 +218,9 @@ static ErtsMMapOp mmap_ops[ERTS_MMAP_OP_RINGBUF_SZ];
#define ERTS_MUNMAP_OP_LCK(PTR, SZ) \
do { \
- erts_smp_mtx_lock(&mmap_state.mtx); \
+ erts_smp_mtx_lock(&mm->mtx); \
ERTS_MUNMAP_OP((PTR), (SZ)); \
- erts_smp_mtx_unlock(&mmap_state.mtx); \
+ erts_smp_mtx_unlock(&mm->mtx); \
} while (0)
#define ERTS_MREMAP_OP_START(OLD_PTR, OLD_SZ, IN_SZ) \
@@ -247,10 +246,10 @@ static ErtsMMapOp mmap_ops[ERTS_MMAP_OP_RINGBUF_SZ];
#define ERTS_MREMAP_OP_LCK(RES, OLD_PTR, OLD_SZ, IN_SZ, OUT_SZ) \
do { \
- erts_smp_mtx_lock(&mmap_state.mtx); \
+ erts_smp_mtx_lock(&mm->mtx); \
ERTS_MREMAP_OP_START((OLD_PTR), (OLD_SZ), (IN_SZ)); \
ERTS_MREMAP_OP_END((RES), (OUT_SZ)); \
- erts_smp_mtx_unlock(&mmap_state.mtx); \
+ erts_smp_mtx_unlock(&mm->mtx); \
} while (0)
#define ERTS_MMAP_OP_ABORT() \
@@ -294,7 +293,7 @@ typedef struct {
Uint nseg;
}ErtsFreeSegMap;
-static struct {
+struct ErtsMemMapper_ {
int (*reserve_physical)(char *, UWord);
void (*unreserve_physical)(char *, UWord);
int supercarrier;
@@ -346,54 +345,62 @@ static struct {
UWord used;
} os;
} size;
-} mmap_state;
+};
+
+ErtsMemMapper erts_dflt_mmapper;
+
+#if defined(ARCH_64) && defined(ERTS_HAVE_OS_PHYSICAL_MEMORY_RESERVATION)
+ErtsMemMapper erts_literal_mmapper;
+char* erts_literals_start;
+UWord erts_literals_size;
+#endif
#define ERTS_MMAP_SIZE_SC_SA_INC(SZ) \
do { \
- mmap_state.size.supercarrier.used.total += (SZ); \
- mmap_state.size.supercarrier.used.sa += (SZ); \
- ERTS_MMAP_ASSERT(mmap_state.size.supercarrier.used.total \
- <= mmap_state.size.supercarrier.total); \
- ERTS_MMAP_ASSERT(mmap_state.size.supercarrier.used.sa \
- <= mmap_state.size.supercarrier.used.total); \
+ mm->size.supercarrier.used.total += (SZ); \
+ mm->size.supercarrier.used.sa += (SZ); \
+ ERTS_MMAP_ASSERT(mm->size.supercarrier.used.total \
+ <= mm->size.supercarrier.total); \
+ ERTS_MMAP_ASSERT(mm->size.supercarrier.used.sa \
+ <= mm->size.supercarrier.used.total); \
} while (0)
#define ERTS_MMAP_SIZE_SC_SA_DEC(SZ) \
do { \
- ERTS_MMAP_ASSERT(mmap_state.size.supercarrier.used.total >= (SZ)); \
- mmap_state.size.supercarrier.used.total -= (SZ); \
- ERTS_MMAP_ASSERT(mmap_state.size.supercarrier.used.sa >= (SZ)); \
- mmap_state.size.supercarrier.used.sa -= (SZ); \
+ ERTS_MMAP_ASSERT(mm->size.supercarrier.used.total >= (SZ)); \
+ mm->size.supercarrier.used.total -= (SZ); \
+ ERTS_MMAP_ASSERT(mm->size.supercarrier.used.sa >= (SZ)); \
+ mm->size.supercarrier.used.sa -= (SZ); \
} while (0)
#define ERTS_MMAP_SIZE_SC_SUA_INC(SZ) \
do { \
- mmap_state.size.supercarrier.used.total += (SZ); \
- mmap_state.size.supercarrier.used.sua += (SZ); \
- ERTS_MMAP_ASSERT(mmap_state.size.supercarrier.used.total \
- <= mmap_state.size.supercarrier.total); \
- ERTS_MMAP_ASSERT(mmap_state.size.supercarrier.used.sua \
- <= mmap_state.size.supercarrier.used.total); \
+ mm->size.supercarrier.used.total += (SZ); \
+ mm->size.supercarrier.used.sua += (SZ); \
+ ERTS_MMAP_ASSERT(mm->size.supercarrier.used.total \
+ <= mm->size.supercarrier.total); \
+ ERTS_MMAP_ASSERT(mm->size.supercarrier.used.sua \
+ <= mm->size.supercarrier.used.total); \
} while (0)
#define ERTS_MMAP_SIZE_SC_SUA_DEC(SZ) \
do { \
- ERTS_MMAP_ASSERT(mmap_state.size.supercarrier.used.total >= (SZ)); \
- mmap_state.size.supercarrier.used.total -= (SZ); \
- ERTS_MMAP_ASSERT(mmap_state.size.supercarrier.used.sua >= (SZ)); \
- mmap_state.size.supercarrier.used.sua -= (SZ); \
+ ERTS_MMAP_ASSERT(mm->size.supercarrier.used.total >= (SZ)); \
+ mm->size.supercarrier.used.total -= (SZ); \
+ ERTS_MMAP_ASSERT(mm->size.supercarrier.used.sua >= (SZ)); \
+ mm->size.supercarrier.used.sua -= (SZ); \
} while (0)
#define ERTS_MMAP_SIZE_OS_INC(SZ) \
do { \
- ERTS_MMAP_ASSERT(mmap_state.size.os.used + (SZ) >= (SZ)); \
- mmap_state.size.os.used += (SZ); \
+ ERTS_MMAP_ASSERT(mm->size.os.used + (SZ) >= (SZ)); \
+ mm->size.os.used += (SZ); \
} while (0)
#define ERTS_MMAP_SIZE_OS_DEC(SZ) \
do { \
- ERTS_MMAP_ASSERT(mmap_state.size.os.used >= (SZ)); \
- mmap_state.size.os.used -= (SZ); \
+ ERTS_MMAP_ASSERT(mm->size.os.used >= (SZ)); \
+ mm->size.os.used -= (SZ); \
} while (0)
static void
-add_free_desc_area(char *start, char *end)
+add_free_desc_area(ErtsMemMapper* mm, char *start, char *end)
{
ERTS_MMAP_ASSERT(end == (void *) 0 || end > start);
if (sizeof(ErtsFreeSegDesc) <= ((UWord) end) - ((UWord) start)) {
@@ -403,7 +410,7 @@ add_free_desc_area(char *start, char *end)
no = 1;
prev_desc = (ErtsFreeSegDesc *) start;
- prev_desc->start = mmap_state.desc.free_list;
+ prev_desc->start = mm->desc.free_list;
desc = (ErtsFreeSegDesc *) (start + sizeof(ErtsFreeSegDesc));
desc_end = start + 2*sizeof(ErtsFreeSegDesc);
@@ -414,59 +421,59 @@ add_free_desc_area(char *start, char *end)
desc_end += sizeof(ErtsFreeSegDesc);
no++;
}
- mmap_state.desc.free_list = (char *) prev_desc;
- mmap_state.no.free_seg_descs += no;
+ mm->desc.free_list = (char *) prev_desc;
+ mm->no.free_seg_descs += no;
}
}
static ErtsFreeSegDesc *
-add_unused_free_desc_area(void)
+add_unused_free_desc_area(ErtsMemMapper* mm)
{
char *ptr;
- if (!mmap_state.desc.unused_start)
+ if (!mm->desc.unused_start)
return NULL;
- ERTS_MMAP_ASSERT(mmap_state.desc.unused_end);
+ ERTS_MMAP_ASSERT(mm->desc.unused_end);
ERTS_MMAP_ASSERT(ERTS_PAGEALIGNED_SIZE
- <= mmap_state.desc.unused_end - mmap_state.desc.unused_start);
+ <= mm->desc.unused_end - mm->desc.unused_start);
- ptr = mmap_state.desc.unused_start + ERTS_PAGEALIGNED_SIZE;
- add_free_desc_area(mmap_state.desc.unused_start, ptr);
+ ptr = mm->desc.unused_start + ERTS_PAGEALIGNED_SIZE;
+ add_free_desc_area(mm, mm->desc.unused_start, ptr);
- if ((mmap_state.desc.unused_end - ptr) >= ERTS_PAGEALIGNED_SIZE)
- mmap_state.desc.unused_start = ptr;
+ if ((mm->desc.unused_end - ptr) >= ERTS_PAGEALIGNED_SIZE)
+ mm->desc.unused_start = ptr;
else
- mmap_state.desc.unused_end = mmap_state.desc.unused_start = NULL;
+ mm->desc.unused_end = mm->desc.unused_start = NULL;
- ERTS_MMAP_ASSERT(mmap_state.desc.free_list);
- return (ErtsFreeSegDesc *) mmap_state.desc.free_list;
+ ERTS_MMAP_ASSERT(mm->desc.free_list);
+ return (ErtsFreeSegDesc *) mm->desc.free_list;
}
static ERTS_INLINE ErtsFreeSegDesc *
-alloc_desc(void)
+alloc_desc(ErtsMemMapper* mm)
{
ErtsFreeSegDesc *res;
- res = (ErtsFreeSegDesc *) mmap_state.desc.free_list;
+ res = (ErtsFreeSegDesc *) mm->desc.free_list;
if (!res) {
- res = add_unused_free_desc_area();
+ res = add_unused_free_desc_area(mm);
if (!res)
return NULL;
}
- mmap_state.desc.free_list = res->start;
- ASSERT(mmap_state.no.free_segs.curr < mmap_state.no.free_seg_descs);
- mmap_state.no.free_segs.curr++;
- if (mmap_state.no.free_segs.max < mmap_state.no.free_segs.curr)
- mmap_state.no.free_segs.max = mmap_state.no.free_segs.curr;
+ mm->desc.free_list = res->start;
+ ASSERT(mm->no.free_segs.curr < mm->no.free_seg_descs);
+ mm->no.free_segs.curr++;
+ if (mm->no.free_segs.max < mm->no.free_segs.curr)
+ mm->no.free_segs.max = mm->no.free_segs.curr;
return res;
}
static ERTS_INLINE void
-free_desc(ErtsFreeSegDesc *desc)
+free_desc(ErtsMemMapper* mm, ErtsFreeSegDesc *desc)
{
- desc->start = mmap_state.desc.free_list;
- mmap_state.desc.free_list = (char *) desc;
- ERTS_MMAP_ASSERT(mmap_state.no.free_segs.curr > 0);
- mmap_state.no.free_segs.curr--;
+ desc->start = mm->desc.free_list;
+ mm->desc.free_list = (char *) desc;
+ ERTS_MMAP_ASSERT(mm->no.free_segs.curr > 0);
+ mm->no.free_segs.curr--;
}
static ERTS_INLINE ErtsFreeSegDesc* anode_to_desc(RBTNode* anode)
@@ -1233,7 +1240,7 @@ Eterm build_free_seg_list(Process* p, ErtsFreeSegMap* map)
# define ERTS_MMAP_FD (-1)
# else
# define ERTS_MMAP_FLAGS (MAP_PRIVATE)
-# define ERTS_MMAP_FD mmap_state.mmap_fd
+# define ERTS_MMAP_FD mm->mmap_fd
# endif
#endif
@@ -1378,11 +1385,12 @@ static void unreserve_noop(char *ptr, UWord size)
}
static UWord
-alloc_desc_insert_free_seg(ErtsFreeSegMap *map, char* start, char* end)
+alloc_desc_insert_free_seg(ErtsMemMapper* mm,
+ ErtsFreeSegMap *map, char* start, char* end)
{
char *ptr;
ErtsFreeSegMap *da_map;
- ErtsFreeSegDesc *desc = alloc_desc();
+ ErtsFreeSegDesc *desc = alloc_desc(mm);
if (desc) {
insert_free_seg(map, desc, start, end);
return 0;
@@ -1395,13 +1403,13 @@ alloc_desc_insert_free_seg(ErtsFreeSegMap *map, char* start, char* end)
*/
#if ERTS_HAVE_OS_MMAP
- if (!mmap_state.no_os_mmap) {
- ptr = os_mmap(mmap_state.desc.new_area_hint, ERTS_PAGEALIGNED_SIZE, 0);
+ if (!mm->no_os_mmap) {
+ ptr = os_mmap(mm->desc.new_area_hint, ERTS_PAGEALIGNED_SIZE, 0);
if (ptr) {
- mmap_state.desc.new_area_hint = ptr+ERTS_PAGEALIGNED_SIZE;
+ mm->desc.new_area_hint = ptr+ERTS_PAGEALIGNED_SIZE;
ERTS_MMAP_SIZE_OS_INC(ERTS_PAGEALIGNED_SIZE);
- add_free_desc_area(ptr, ptr+ERTS_PAGEALIGNED_SIZE);
- desc = alloc_desc();
+ add_free_desc_area(mm, ptr, ptr+ERTS_PAGEALIGNED_SIZE);
+ desc = alloc_desc(mm);
ERTS_MMAP_ASSERT(desc);
insert_free_seg(map, desc, start, end);
return 0;
@@ -1412,20 +1420,20 @@ alloc_desc_insert_free_seg(ErtsFreeSegMap *map, char* start, char* end)
/*
* ...then try to find a good place in the supercarrier...
*/
- da_map = &mmap_state.sua.map;
+ da_map = &mm->sua.map;
desc = lookup_free_seg(da_map, ERTS_PAGEALIGNED_SIZE);
if (desc) {
- if (mmap_state.reserve_physical(desc->start, ERTS_PAGEALIGNED_SIZE))
+ if (mm->reserve_physical(desc->start, ERTS_PAGEALIGNED_SIZE))
ERTS_MMAP_SIZE_SC_SUA_INC(ERTS_PAGEALIGNED_SIZE);
else
desc = NULL;
}
else {
- da_map = &mmap_state.sa.map;
+ da_map = &mm->sa.map;
desc = lookup_free_seg(da_map, ERTS_PAGEALIGNED_SIZE);
if (desc) {
- if (mmap_state.reserve_physical(desc->start, ERTS_PAGEALIGNED_SIZE))
+ if (mm->reserve_physical(desc->start, ERTS_PAGEALIGNED_SIZE))
ERTS_MMAP_SIZE_SC_SA_INC(ERTS_PAGEALIGNED_SIZE);
else
desc = NULL;
@@ -1433,15 +1441,15 @@ alloc_desc_insert_free_seg(ErtsFreeSegMap *map, char* start, char* end)
}
if (desc) {
char *da_end = desc->start + ERTS_PAGEALIGNED_SIZE;
- add_free_desc_area(desc->start, da_end);
+ add_free_desc_area(mm, desc->start, da_end);
if (da_end != desc->end)
resize_free_seg(da_map, desc, da_end, desc->end);
else {
delete_free_seg(da_map, desc);
- free_desc(desc);
+ free_desc(mm, desc);
}
- desc = alloc_desc();
+ desc = alloc_desc(mm);
ERTS_MMAP_ASSERT(desc);
insert_free_seg(map, desc, start, end);
return 0;
@@ -1454,10 +1462,10 @@ alloc_desc_insert_free_seg(ErtsFreeSegMap *map, char* start, char* end)
ptr = start + ERTS_PAGEALIGNED_SIZE;
ERTS_MMAP_ASSERT(ptr <= end);
- add_free_desc_area(start, ptr);
+ add_free_desc_area(mm, start, ptr);
if (ptr != end) {
- desc = alloc_desc();
+ desc = alloc_desc(mm);
ERTS_MMAP_ASSERT(desc);
insert_free_seg(map, desc, ptr, end);
}
@@ -1466,46 +1474,46 @@ alloc_desc_insert_free_seg(ErtsFreeSegMap *map, char* start, char* end)
}
void *
-erts_mmap(Uint32 flags, UWord *sizep)
+erts_mmap(ErtsMemMapper* mm, Uint32 flags, UWord *sizep)
{
char *seg;
UWord asize = ERTS_PAGEALIGNED_CEILING(*sizep);
/* Map in premapped supercarrier */
- if (mmap_state.supercarrier && !(ERTS_MMAPFLG_OS_ONLY & flags)) {
+ if (mm->supercarrier && !(ERTS_MMAPFLG_OS_ONLY & flags)) {
char *end;
ErtsFreeSegDesc *desc;
Uint32 superaligned = (ERTS_MMAPFLG_SUPERALIGNED & flags);
- erts_smp_mtx_lock(&mmap_state.mtx);
+ erts_smp_mtx_lock(&mm->mtx);
ERTS_MMAP_OP_START(*sizep);
if (!superaligned) {
- desc = lookup_free_seg(&mmap_state.sua.map, asize);
+ desc = lookup_free_seg(&mm->sua.map, asize);
if (desc) {
seg = desc->start;
end = seg+asize;
- if (!mmap_state.reserve_physical(seg, asize))
+ if (!mm->reserve_physical(seg, asize))
goto supercarrier_reserve_failure;
if (desc->end == end) {
- delete_free_seg(&mmap_state.sua.map, desc);
- free_desc(desc);
+ delete_free_seg(&mm->sua.map, desc);
+ free_desc(mm, desc);
}
else {
ERTS_MMAP_ASSERT(end < desc->end);
- resize_free_seg(&mmap_state.sua.map, desc, end, desc->end);
+ resize_free_seg(&mm->sua.map, desc, end, desc->end);
}
ERTS_MMAP_SIZE_SC_SUA_INC(asize);
goto supercarrier_success;
}
- if (asize <= mmap_state.sua.bot - mmap_state.sa.top) {
- if (!mmap_state.reserve_physical(mmap_state.sua.bot - asize,
+ if (asize <= mm->sua.bot - mm->sa.top) {
+ if (!mm->reserve_physical(mm->sua.bot - asize,
asize))
goto supercarrier_reserve_failure;
- mmap_state.sua.bot -= asize;
- seg = mmap_state.sua.bot;
+ mm->sua.bot -= asize;
+ seg = mm->sua.bot;
ERTS_MMAP_SIZE_SC_SUA_INC(asize);
goto supercarrier_success;
}
@@ -1513,84 +1521,84 @@ erts_mmap(Uint32 flags, UWord *sizep)
asize = ERTS_SUPERALIGNED_CEILING(asize);
- desc = lookup_free_seg(&mmap_state.sa.map, asize);
+ desc = lookup_free_seg(&mm->sa.map, asize);
if (desc) {
char *start = seg = desc->start;
seg = (char *) ERTS_SUPERALIGNED_CEILING(seg);
end = seg+asize;
- if (!mmap_state.reserve_physical(start, (UWord) (end - start)))
+ if (!mm->reserve_physical(start, (UWord) (end - start)))
goto supercarrier_reserve_failure;
ERTS_MMAP_SIZE_SC_SA_INC(asize);
if (desc->end == end) {
if (start != seg)
- resize_free_seg(&mmap_state.sa.map, desc, start, seg);
+ resize_free_seg(&mm->sa.map, desc, start, seg);
else {
- delete_free_seg(&mmap_state.sa.map, desc);
- free_desc(desc);
+ delete_free_seg(&mm->sa.map, desc);
+ free_desc(mm, desc);
}
}
else {
ERTS_MMAP_ASSERT(end < desc->end);
- resize_free_seg(&mmap_state.sa.map, desc, end, desc->end);
+ resize_free_seg(&mm->sa.map, desc, end, desc->end);
if (start != seg) {
UWord ad_sz;
- ad_sz = alloc_desc_insert_free_seg(&mmap_state.sua.map,
+ ad_sz = alloc_desc_insert_free_seg(mm, &mm->sua.map,
start, seg);
start += ad_sz;
if (start != seg)
- mmap_state.unreserve_physical(start, (UWord) (seg - start));
+ mm->unreserve_physical(start, (UWord) (seg - start));
}
}
goto supercarrier_success;
}
if (superaligned) {
- char *start = mmap_state.sa.top;
+ char *start = mm->sa.top;
seg = (char *) ERTS_SUPERALIGNED_CEILING(start);
- if (asize + (seg - start) <= mmap_state.sua.bot - start) {
+ if (asize + (seg - start) <= mm->sua.bot - start) {
end = seg + asize;
- if (!mmap_state.reserve_physical(start, (UWord) (end - start)))
+ if (!mm->reserve_physical(start, (UWord) (end - start)))
goto supercarrier_reserve_failure;
- mmap_state.sa.top = end;
+ mm->sa.top = end;
ERTS_MMAP_SIZE_SC_SA_INC(asize);
if (start != seg) {
UWord ad_sz;
- ad_sz = alloc_desc_insert_free_seg(&mmap_state.sua.map,
+ ad_sz = alloc_desc_insert_free_seg(mm, &mm->sua.map,
start, seg);
start += ad_sz;
if (start != seg)
- mmap_state.unreserve_physical(start, (UWord) (seg - start));
+ mm->unreserve_physical(start, (UWord) (seg - start));
}
goto supercarrier_success;
}
- desc = lookup_free_seg(&mmap_state.sua.map, asize + ERTS_SUPERALIGNED_SIZE);
+ desc = lookup_free_seg(&mm->sua.map, asize + ERTS_SUPERALIGNED_SIZE);
if (desc) {
char *org_start = desc->start;
char *org_end = desc->end;
seg = (char *) ERTS_SUPERALIGNED_CEILING(org_start);
end = seg + asize;
- if (!mmap_state.reserve_physical(seg, (UWord) (org_end - seg)))
+ if (!mm->reserve_physical(seg, (UWord) (org_end - seg)))
goto supercarrier_reserve_failure;
ERTS_MMAP_SIZE_SC_SUA_INC(asize);
if (org_start != seg) {
ERTS_MMAP_ASSERT(org_start < seg);
- resize_free_seg(&mmap_state.sua.map, desc, org_start, seg);
+ resize_free_seg(&mm->sua.map, desc, org_start, seg);
desc = NULL;
}
if (end != org_end) {
UWord ad_sz = 0;
ERTS_MMAP_ASSERT(end < org_end);
if (desc)
- resize_free_seg(&mmap_state.sua.map, desc, end, org_end);
+ resize_free_seg(&mm->sua.map, desc, end, org_end);
else
- ad_sz = alloc_desc_insert_free_seg(&mmap_state.sua.map,
+ ad_sz = alloc_desc_insert_free_seg(mm, &mm->sua.map,
end, org_end);
end += ad_sz;
if (end != org_end)
- mmap_state.unreserve_physical(end,
+ mm->unreserve_physical(end,
(UWord) (org_end - end));
}
goto supercarrier_success;
@@ -1598,12 +1606,12 @@ erts_mmap(Uint32 flags, UWord *sizep)
}
ERTS_MMAP_OP_ABORT();
- erts_smp_mtx_unlock(&mmap_state.mtx);
+ erts_smp_mtx_unlock(&mm->mtx);
}
#if ERTS_HAVE_OS_MMAP
/* Map using OS primitives */
- if (!(ERTS_MMAPFLG_SUPERCARRIER_ONLY & flags) && !mmap_state.no_os_mmap) {
+ if (!(ERTS_MMAPFLG_SUPERCARRIER_ONLY & flags) && !mm->no_os_mmap) {
if (!(ERTS_MMAPFLG_SUPERALIGNED & flags)) {
seg = os_mmap(NULL, asize, 0);
if (!seg)
@@ -1661,25 +1669,25 @@ supercarrier_success:
#endif
ERTS_MMAP_OP_END(seg, asize);
- erts_smp_mtx_unlock(&mmap_state.mtx);
+ erts_smp_mtx_unlock(&mm->mtx);
*sizep = asize;
return (void *) seg;
supercarrier_reserve_failure:
- erts_smp_mtx_unlock(&mmap_state.mtx);
+ erts_smp_mtx_unlock(&mm->mtx);
*sizep = 0;
return NULL;
}
void
-erts_munmap(Uint32 flags, void *ptr, UWord size)
+erts_munmap(ErtsMemMapper* mm, Uint32 flags, void *ptr, UWord size)
{
ERTS_MMAP_ASSERT(ERTS_IS_PAGEALIGNED(ptr));
ERTS_MMAP_ASSERT(ERTS_IS_PAGEALIGNED(size));
if (!ERTS_MMAP_IN_SUPERCARRIER(ptr)) {
- ERTS_MMAP_ASSERT(!mmap_state.no_os_mmap);
+ ERTS_MMAP_ASSERT(!mm->no_os_mmap);
#if ERTS_HAVE_OS_MMAP
ERTS_MUNMAP_OP_LCK(ptr, size);
ERTS_MMAP_SIZE_OS_DEC(size);
@@ -1692,45 +1700,45 @@ erts_munmap(Uint32 flags, void *ptr, UWord size)
ErtsFreeSegDesc *prev, *next, *desc;
UWord ad_sz = 0;
- ERTS_MMAP_ASSERT(mmap_state.supercarrier);
+ ERTS_MMAP_ASSERT(mm->supercarrier);
start = (char *) ptr;
end = start + size;
- erts_smp_mtx_lock(&mmap_state.mtx);
+ erts_smp_mtx_lock(&mm->mtx);
ERTS_MUNMAP_OP(ptr, size);
if (ERTS_MMAP_IN_SUPERALIGNED_AREA(ptr)) {
- map = &mmap_state.sa.map;
+ map = &mm->sa.map;
adjacent_free_seg(map, start, end, &prev, &next);
ERTS_MMAP_SIZE_SC_SA_DEC(size);
- if (end == mmap_state.sa.top) {
+ if (end == mm->sa.top) {
ERTS_MMAP_ASSERT(!next);
if (prev) {
start = prev->start;
delete_free_seg(map, prev);
- free_desc(prev);
+ free_desc(mm, prev);
}
- mmap_state.sa.top = start;
+ mm->sa.top = start;
goto supercarrier_success;
}
}
else {
- map = &mmap_state.sua.map;
+ map = &mm->sua.map;
adjacent_free_seg(map, start, end, &prev, &next);
ERTS_MMAP_SIZE_SC_SUA_DEC(size);
- if (start == mmap_state.sua.bot) {
+ if (start == mm->sua.bot) {
ERTS_MMAP_ASSERT(!prev);
if (next) {
end = next->end;
delete_free_seg(map, next);
- free_desc(next);
+ free_desc(mm, next);
}
- mmap_state.sua.bot = end;
+ mm->sua.bot = end;
goto supercarrier_success;
}
}
@@ -1742,7 +1750,7 @@ erts_munmap(Uint32 flags, void *ptr, UWord size)
end = next->end;
if (prev) {
delete_free_seg(map, next);
- free_desc(next);
+ free_desc(mm, next);
goto save_prev;
}
desc = next;
@@ -1756,7 +1764,7 @@ erts_munmap(Uint32 flags, void *ptr, UWord size)
if (desc)
resize_free_seg(map, desc, start, end);
else
- ad_sz = alloc_desc_insert_free_seg(map, start, end);
+ ad_sz = alloc_desc_insert_free_seg(mm, map, start, end);
supercarrier_success: {
UWord unres_sz;
@@ -1764,30 +1772,32 @@ erts_munmap(Uint32 flags, void *ptr, UWord size)
ERTS_MMAP_ASSERT(size >= ad_sz);
unres_sz = size - ad_sz;
if (unres_sz)
- mmap_state.unreserve_physical(((char *) ptr) + ad_sz, unres_sz);
+ mm->unreserve_physical(((char *) ptr) + ad_sz, unres_sz);
- erts_smp_mtx_unlock(&mmap_state.mtx);
+ erts_smp_mtx_unlock(&mm->mtx);
}
}
}
static void *
-remap_move(Uint32 flags, void *ptr, UWord old_size, UWord *sizep)
+remap_move(ErtsMemMapper* mm,
+ Uint32 flags, void *ptr, UWord old_size, UWord *sizep)
{
UWord size = *sizep;
- void *new_ptr = erts_mmap(flags, &size);
+ void *new_ptr = erts_mmap(mm, flags, &size);
if (!new_ptr)
return NULL;
*sizep = size;
if (old_size < size)
size = old_size;
sys_memcpy(new_ptr, ptr, (size_t) size);
- erts_munmap(flags, ptr, old_size);
+ erts_munmap(mm, flags, ptr, old_size);
return new_ptr;
}
void *
-erts_mremap(Uint32 flags, void *ptr, UWord old_size, UWord *sizep)
+erts_mremap(ErtsMemMapper* mm,
+ Uint32 flags, void *ptr, UWord old_size, UWord *sizep)
{
void *new_ptr;
Uint32 superaligned;
@@ -1799,11 +1809,11 @@ erts_mremap(Uint32 flags, void *ptr, UWord old_size, UWord *sizep)
if (!ERTS_MMAP_IN_SUPERCARRIER(ptr)) {
- ERTS_MMAP_ASSERT(!mmap_state.no_os_mmap);
+ ERTS_MMAP_ASSERT(!mm->no_os_mmap);
- if (!(ERTS_MMAPFLG_OS_ONLY & flags) && mmap_state.supercarrier) {
- new_ptr = remap_move(ERTS_MMAPFLG_SUPERCARRIER_ONLY|flags, ptr,
- old_size, sizep);
+ if (!(ERTS_MMAPFLG_OS_ONLY & flags) && mm->supercarrier) {
+ new_ptr = remap_move(mm, ERTS_MMAPFLG_SUPERCARRIER_ONLY|flags,
+ ptr, old_size, sizep);
if (new_ptr)
return new_ptr;
}
@@ -1850,7 +1860,7 @@ erts_mremap(Uint32 flags, void *ptr, UWord old_size, UWord *sizep)
#endif
#if ERTS_HAVE_OS_MREMAP
if (superaligned)
- return remap_move(flags, new_ptr, old_size, sizep);
+ return remap_move(mm, flags, new_ptr, old_size, sizep);
else {
new_ptr = os_mremap(ptr, old_size, asize, 0);
if (!new_ptr)
@@ -1872,10 +1882,10 @@ erts_mremap(Uint32 flags, void *ptr, UWord old_size, UWord *sizep)
ErtsFreeSegDesc *prev, *next;
UWord ad_sz = 0;
- ERTS_MMAP_ASSERT(mmap_state.supercarrier);
+ ERTS_MMAP_ASSERT(mm->supercarrier);
if (ERTS_MMAPFLG_OS_ONLY & flags)
- return remap_move(flags, ptr, old_size, sizep);
+ return remap_move(mm, flags, ptr, old_size, sizep);
superaligned = (ERTS_MMAPFLG_SUPERALIGNED & flags);
@@ -1883,19 +1893,19 @@ erts_mremap(Uint32 flags, void *ptr, UWord old_size, UWord *sizep)
? ERTS_SUPERALIGNED_CEILING(*sizep)
: ERTS_PAGEALIGNED_CEILING(*sizep));
- erts_smp_mtx_lock(&mmap_state.mtx);
+ erts_smp_mtx_lock(&mm->mtx);
if (ERTS_MMAP_IN_SUPERALIGNED_AREA(ptr)
- ? (!superaligned && lookup_free_seg(&mmap_state.sua.map, asize))
- : (superaligned && lookup_free_seg(&mmap_state.sa.map, asize))) {
- erts_smp_mtx_unlock(&mmap_state.mtx);
+ ? (!superaligned && lookup_free_seg(&mm->sua.map, asize))
+ : (superaligned && lookup_free_seg(&mm->sa.map, asize))) {
+ erts_smp_mtx_unlock(&mm->mtx);
/*
* Segment currently in wrong area (due to a previous memory
* shortage), move it to the right area.
* (remap_move() will succeed)
*/
- return remap_move(ERTS_MMAPFLG_SUPERCARRIER_ONLY|flags, ptr,
- old_size, sizep);
+ return remap_move(mm, ERTS_MMAPFLG_SUPERCARRIER_ONLY|flags,
+ ptr, old_size, sizep);
}
ERTS_MREMAP_OP_START(ptr, old_size, *sizep);
@@ -1917,18 +1927,18 @@ erts_mremap(Uint32 flags, void *ptr, UWord old_size, UWord *sizep)
UWord unres_sz;
new_ptr = ptr;
if (!ERTS_MMAP_IN_SUPERALIGNED_AREA(ptr)) {
- map = &mmap_state.sua.map;
+ map = &mm->sua.map;
ERTS_MMAP_SIZE_SC_SUA_DEC(old_size - asize);
}
else {
- if (end == mmap_state.sa.top) {
- mmap_state.sa.top = new_end;
- mmap_state.unreserve_physical(((char *) ptr) + asize,
+ if (end == mm->sa.top) {
+ mm->sa.top = new_end;
+ mm->unreserve_physical(((char *) ptr) + asize,
old_size - asize);
goto supercarrier_resize_success;
}
ERTS_MMAP_SIZE_SC_SA_DEC(old_size - asize);
- map = &mmap_state.sa.map;
+ map = &mm->sa.map;
}
adjacent_free_seg(map, start, end, &prev, &next);
@@ -1936,11 +1946,11 @@ erts_mremap(Uint32 flags, void *ptr, UWord old_size, UWord *sizep)
if (next)
resize_free_seg(map, next, new_end, next->end);
else
- ad_sz = alloc_desc_insert_free_seg(map, new_end, end);
+ ad_sz = alloc_desc_insert_free_seg(mm, map, new_end, end);
ERTS_MMAP_ASSERT(old_size - asize >= ad_sz);
unres_sz = old_size - asize - ad_sz;
if (unres_sz)
- mmap_state.unreserve_physical(((char *) ptr) + asize + ad_sz,
+ mm->unreserve_physical(((char *) ptr) + asize + ad_sz,
unres_sz);
goto supercarrier_resize_success;
}
@@ -1950,17 +1960,17 @@ erts_mremap(Uint32 flags, void *ptr, UWord old_size, UWord *sizep)
ERTS_MMAP_ASSERT(ERTS_IS_PAGEALIGNED(old_size));
ERTS_MMAP_ASSERT(ERTS_IS_PAGEALIGNED(asize));
- adjacent_free_seg(&mmap_state.sua.map, start, end, &prev, &next);
+ adjacent_free_seg(&mm->sua.map, start, end, &prev, &next);
if (next && new_end <= next->end) {
- if (!mmap_state.reserve_physical(((char *) ptr) + old_size,
+ if (!mm->reserve_physical(((char *) ptr) + old_size,
asize - old_size))
goto supercarrier_reserve_failure;
if (new_end < next->end)
- resize_free_seg(&mmap_state.sua.map, next, new_end, next->end);
+ resize_free_seg(&mm->sua.map, next, new_end, next->end);
else {
- delete_free_seg(&mmap_state.sua.map, next);
- free_desc(next);
+ delete_free_seg(&mm->sua.map, next);
+ free_desc(mm, next);
}
new_ptr = ptr;
ERTS_MMAP_SIZE_SC_SUA_INC(asize - old_size);
@@ -1969,28 +1979,28 @@ erts_mremap(Uint32 flags, void *ptr, UWord old_size, UWord *sizep)
}
else { /* Superaligned area */
- if (end == mmap_state.sa.top) {
- if (new_end <= mmap_state.sua.bot) {
- if (!mmap_state.reserve_physical(((char *) ptr) + old_size,
+ if (end == mm->sa.top) {
+ if (new_end <= mm->sua.bot) {
+ if (!mm->reserve_physical(((char *) ptr) + old_size,
asize - old_size))
goto supercarrier_reserve_failure;
- mmap_state.sa.top = new_end;
+ mm->sa.top = new_end;
new_ptr = ptr;
ERTS_MMAP_SIZE_SC_SA_INC(asize - old_size);
goto supercarrier_resize_success;
}
}
else {
- adjacent_free_seg(&mmap_state.sa.map, start, end, &prev, &next);
+ adjacent_free_seg(&mm->sa.map, start, end, &prev, &next);
if (next && new_end <= next->end) {
- if (!mmap_state.reserve_physical(((char *) ptr) + old_size,
+ if (!mm->reserve_physical(((char *) ptr) + old_size,
asize - old_size))
goto supercarrier_reserve_failure;
if (new_end < next->end)
- resize_free_seg(&mmap_state.sa.map, next, new_end, next->end);
+ resize_free_seg(&mm->sa.map, next, new_end, next->end);
else {
- delete_free_seg(&mmap_state.sa.map, next);
- free_desc(next);
+ delete_free_seg(&mm->sa.map, next);
+ free_desc(mm, next);
}
new_ptr = ptr;
ERTS_MMAP_SIZE_SC_SA_INC(asize - old_size);
@@ -2000,12 +2010,12 @@ erts_mremap(Uint32 flags, void *ptr, UWord old_size, UWord *sizep)
}
ERTS_MMAP_OP_ABORT();
- erts_smp_mtx_unlock(&mmap_state.mtx);
+ erts_smp_mtx_unlock(&mm->mtx);
/* Failed to resize... */
}
- return remap_move(flags, ptr, old_size, sizep);
+ return remap_move(mm, flags, ptr, old_size, sizep);
supercarrier_resize_success:
@@ -2022,25 +2032,24 @@ supercarrier_resize_success:
#endif
ERTS_MREMAP_OP_END(new_ptr, asize);
- erts_smp_mtx_unlock(&mmap_state.mtx);
+ erts_smp_mtx_unlock(&mm->mtx);
*sizep = asize;
return new_ptr;
supercarrier_reserve_failure:
ERTS_MREMAP_OP_END(NULL, old_size);
- erts_smp_mtx_unlock(&mmap_state.mtx);
+ erts_smp_mtx_unlock(&mm->mtx);
*sizep = old_size;
return NULL;
}
-int erts_mmap_in_supercarrier(void *ptr)
+int erts_mmap_in_supercarrier(ErtsMemMapper* mm, void *ptr)
{
return ERTS_MMAP_IN_SUPERCARRIER(ptr);
}
-
static struct {
Eterm total;
Eterm total_sa;
@@ -2103,8 +2112,9 @@ static void hard_dbg_mseg_init(void);
#endif
void
-erts_mmap_init(ErtsMMapInit *init)
+erts_mmap_init(ErtsMemMapper* mm, ErtsMMapInit *init)
{
+ static int is_first_call = 1;
int virtual_map = 0;
char *start = NULL, *end = NULL;
UWord pagesize;
@@ -2131,20 +2141,20 @@ erts_mmap_init(ErtsMMapInit *init)
ERTS_MMAP_OP_RINGBUF_INIT();
- erts_have_erts_mmap = 0;
-
- mmap_state.supercarrier = 0;
- mmap_state.reserve_physical = reserve_noop;
- mmap_state.unreserve_physical = unreserve_noop;
+ mm->supercarrier = 0;
+ mm->reserve_physical = reserve_noop;
+ mm->unreserve_physical = unreserve_noop;
#if HAVE_MMAP && !defined(MAP_ANON)
- mmap_state.mmap_fd = open("/dev/zero", O_RDWR);
- if (mmap_state.mmap_fd < 0)
+ mm->mmap_fd = open("/dev/zero", O_RDWR);
+ if (mm->mmap_fd < 0)
erl_exit(-1, "erts_mmap: Failed to open /dev/zero\n");
#endif
- erts_smp_mtx_init(&mmap_state.mtx, "erts_mmap");
- erts_mtx_init(&am.init_mutex, "mmap_init_atoms");
+ erts_smp_mtx_init(&mm->mtx, "erts_mmap");
+ if (is_first_call) {
+ erts_mtx_init(&am.init_mutex, "mmap_init_atoms");
+ }
#ifdef ERTS_HAVE_OS_PHYSICAL_MEMORY_RESERVATION
if (init->virtual_range.start) {
@@ -2160,8 +2170,8 @@ erts_mmap_init(ErtsMMapInit *init)
sz = start - ptr;
if (sz)
os_munmap(end, sz);
- mmap_state.reserve_physical = os_reserve_physical;
- mmap_state.unreserve_physical = os_unreserve_physical;
+ mm->reserve_physical = os_reserve_physical;
+ mm->unreserve_physical = os_unreserve_physical;
virtual_map = 1;
}
else
@@ -2179,8 +2189,8 @@ erts_mmap_init(ErtsMMapInit *init)
#ifdef ERTS_HAVE_OS_PHYSICAL_MEMORY_RESERVATION
if (!init->scrpm) {
start = os_mmap_virtual(NULL, sz);
- mmap_state.reserve_physical = os_reserve_physical;
- mmap_state.unreserve_physical = os_unreserve_physical;
+ mm->reserve_physical = os_reserve_physical;
+ mm->unreserve_physical = os_unreserve_physical;
virtual_map = 1;
}
else
@@ -2206,34 +2216,32 @@ erts_mmap_init(ErtsMMapInit *init)
}
#endif
}
- if (!mmap_state.no_os_mmap)
- erts_have_erts_mmap |= ERTS_HAVE_ERTS_OS_MMAP;
#endif
- mmap_state.no.free_seg_descs = 0;
- mmap_state.no.free_segs.curr = 0;
- mmap_state.no.free_segs.max = 0;
+ mm->no.free_seg_descs = 0;
+ mm->no.free_segs.curr = 0;
+ mm->no.free_segs.max = 0;
- mmap_state.size.supercarrier.total = 0;
- mmap_state.size.supercarrier.used.total = 0;
- mmap_state.size.supercarrier.used.sa = 0;
- mmap_state.size.supercarrier.used.sua = 0;
- mmap_state.size.os.used = 0;
+ mm->size.supercarrier.total = 0;
+ mm->size.supercarrier.used.total = 0;
+ mm->size.supercarrier.used.sa = 0;
+ mm->size.supercarrier.used.sua = 0;
+ mm->size.os.used = 0;
- mmap_state.desc.new_area_hint = NULL;
+ mm->desc.new_area_hint = NULL;
if (!start) {
- mmap_state.sa.bot = NULL;
- mmap_state.sua.top = NULL;
- mmap_state.sa.bot = NULL;
- mmap_state.sua.top = NULL;
- mmap_state.no_os_mmap = 0;
- mmap_state.supercarrier = 0;
+ mm->sa.bot = NULL;
+ mm->sua.top = NULL;
+ mm->sa.bot = NULL;
+ mm->sua.top = NULL;
+ mm->no_os_mmap = 0;
+ mm->supercarrier = 0;
}
else {
size_t desc_size;
- mmap_state.no_os_mmap = init->sco;
+ mm->no_os_mmap = init->sco;
desc_size = init->scrfsd;
if (desc_size < 100)
@@ -2244,66 +2252,73 @@ erts_mmap_init(ErtsMMapInit *init)
+ ERTS_PAGEALIGNED_SIZE) > end - start)
erl_exit(-1, "erts_mmap: No space for segments in super carrier\n");
- mmap_state.sa.bot = start;
- mmap_state.sa.bot += desc_size;
- mmap_state.sa.bot = (char *) ERTS_SUPERALIGNED_CEILING(mmap_state.sa.bot);
- mmap_state.sa.top = mmap_state.sa.bot;
- mmap_state.sua.top = end;
- mmap_state.sua.bot = mmap_state.sua.top;
+ mm->sa.bot = start;
+ mm->sa.bot += desc_size;
+ mm->sa.bot = (char *) ERTS_SUPERALIGNED_CEILING(mm->sa.bot);
+ mm->sa.top = mm->sa.bot;
+ mm->sua.top = end;
+ mm->sua.bot = mm->sua.top;
- mmap_state.size.supercarrier.used.total += (UWord) (mmap_state.sa.bot - start);
+ mm->size.supercarrier.used.total += (UWord) (mm->sa.bot - start);
- mmap_state.desc.free_list = NULL;
- mmap_state.desc.reserved = 0;
+ mm->desc.free_list = NULL;
+ mm->desc.reserved = 0;
if (end == (void *) 0) {
/*
* Very unlikely, but we need a guarantee
- * that `mmap_state.sua.top` always will
+ * that `mm->sua.top` always will
* compare as larger than all segment pointers
* into the super carrier...
*/
- mmap_state.sua.top -= ERTS_PAGEALIGNED_SIZE;
- mmap_state.size.supercarrier.used.total += ERTS_PAGEALIGNED_SIZE;
+ mm->sua.top -= ERTS_PAGEALIGNED_SIZE;
+ mm->size.supercarrier.used.total += ERTS_PAGEALIGNED_SIZE;
#ifdef ERTS_HAVE_OS_PHYSICAL_MEMORY_RESERVATION
- if (!virtual_map || os_reserve_physical(mmap_state.sua.top, ERTS_PAGEALIGNED_SIZE))
+ if (!virtual_map || os_reserve_physical(mm->sua.top, ERTS_PAGEALIGNED_SIZE))
#endif
- add_free_desc_area(mmap_state.sua.top, end);
- mmap_state.desc.reserved += (end - mmap_state.sua.top) / sizeof(ErtsFreeSegDesc);
+ add_free_desc_area(mm, mm->sua.top, end);
+ mm->desc.reserved += (end - mm->sua.top) / sizeof(ErtsFreeSegDesc);
}
- mmap_state.size.supercarrier.total = (UWord) (mmap_state.sua.top - start);
+ mm->size.supercarrier.total = (UWord) (mm->sua.top - start);
/*
* Area before (and after) super carrier
* will be used for free segment descritors.
*/
#ifdef ERTS_HAVE_OS_PHYSICAL_MEMORY_RESERVATION
- if (virtual_map && !os_reserve_physical(start, mmap_state.sa.bot - start))
+ if (virtual_map && !os_reserve_physical(start, mm->sa.bot - start))
erl_exit(-1, "erts_mmap: Failed to reserve physical memory for descriptors\n");
#endif
- mmap_state.desc.unused_start = start;
- mmap_state.desc.unused_end = mmap_state.sa.bot;
- mmap_state.desc.reserved += ((mmap_state.desc.unused_end - start)
+ mm->desc.unused_start = start;
+ mm->desc.unused_end = mm->sa.bot;
+ mm->desc.reserved += ((mm->desc.unused_end - start)
/ sizeof(ErtsFreeSegDesc));
- init_free_seg_map(&mmap_state.sa.map, SA_SZ_ADDR_ORDER);
- init_free_seg_map(&mmap_state.sua.map, SZ_REVERSE_ADDR_ORDER);
+ init_free_seg_map(&mm->sa.map, SA_SZ_ADDR_ORDER);
+ init_free_seg_map(&mm->sua.map, SZ_REVERSE_ADDR_ORDER);
- mmap_state.supercarrier = 1;
- erts_have_erts_mmap |= ERTS_HAVE_ERTS_SUPERCARRIER_MMAP;
+ mm->supercarrier = 1;
- mmap_state.desc.new_area_hint = end;
+ mm->desc.new_area_hint = end;
}
#if !ERTS_HAVE_OS_MMAP
- mmap_state.no_os_mmap = 1;
+ mm->no_os_mmap = 1;
#endif
#ifdef HARD_DEBUG_MSEG
hard_dbg_mseg_init();
#endif
+
+#if defined(ARCH_64) && defined(ERTS_HAVE_OS_PHYSICAL_MEMORY_RESERVATION)
+ if (mm == &erts_literal_mmapper) {
+ erts_literals_start = erts_literal_mmapper.sa.bot;
+ erts_literals_size = erts_literal_mmapper.sua.top - erts_literals_start;
+ }
+#endif
+ is_first_call = 0;
}
@@ -2313,7 +2328,8 @@ add_2tup(Uint **hpp, Uint *szp, Eterm *lp, Eterm el1, Eterm el2)
*lp = erts_bld_cons(hpp, szp, erts_bld_tuple(hpp, szp, 2, el1, el2), *lp);
}
-Eterm erts_mmap_info(int *print_to_p,
+Eterm erts_mmap_info(ErtsMemMapper* mm,
+ int *print_to_p,
void *print_to_arg,
Eterm** hpp, Uint* szp,
struct erts_mmap_info_struct* emis)
@@ -2328,29 +2344,29 @@ Eterm erts_mmap_info(int *print_to_p,
Eterm res = THE_NON_VALUE;
if (!hpp) {
- erts_smp_mtx_lock(&mmap_state.mtx);
- emis->sizes[0] = mmap_state.size.supercarrier.total;
- emis->sizes[1] = mmap_state.sa.top - mmap_state.sa.bot;
- emis->sizes[2] = mmap_state.sua.top - mmap_state.sua.bot;
- emis->sizes[3] = mmap_state.size.supercarrier.used.total;
- emis->sizes[4] = mmap_state.size.supercarrier.used.sa;
- emis->sizes[5] = mmap_state.size.supercarrier.used.sua;
+ erts_smp_mtx_lock(&mm->mtx);
+ emis->sizes[0] = mm->size.supercarrier.total;
+ emis->sizes[1] = mm->sa.top - mm->sa.bot;
+ emis->sizes[2] = mm->sua.top - mm->sua.bot;
+ emis->sizes[3] = mm->size.supercarrier.used.total;
+ emis->sizes[4] = mm->size.supercarrier.used.sa;
+ emis->sizes[5] = mm->size.supercarrier.used.sua;
- emis->segs[0] = mmap_state.no.free_segs.curr;
- emis->segs[1] = mmap_state.no.free_segs.max;
- emis->segs[2] = mmap_state.no.free_seg_descs;
- emis->segs[3] = mmap_state.desc.reserved;
- emis->segs[4] = mmap_state.sa.map.nseg;
- emis->segs[5] = mmap_state.sua.map.nseg;
+ emis->segs[0] = mm->no.free_segs.curr;
+ emis->segs[1] = mm->no.free_segs.max;
+ emis->segs[2] = mm->no.free_seg_descs;
+ emis->segs[3] = mm->desc.reserved;
+ emis->segs[4] = mm->sa.map.nseg;
+ emis->segs[5] = mm->sua.map.nseg;
- emis->os_used = mmap_state.size.os.used;
- erts_smp_mtx_unlock(&mmap_state.mtx);
+ emis->os_used = mm->size.os.used;
+ erts_smp_mtx_unlock(&mm->mtx);
}
if (print_to_p) {
int to = *print_to_p;
void *arg = print_to_arg;
- if (mmap_state.supercarrier) {
+ if (mm->supercarrier) {
const char* prefix = "supercarrier ";
erts_print(to, arg, "%stotal size: %bpu\n", prefix, emis->sizes[0]);
erts_print(to, arg, "%stotal sa size: %bpu\n", prefix, emis->sizes[1]);
@@ -2365,7 +2381,7 @@ Eterm erts_mmap_info(int *print_to_p,
erts_print(to, arg, "%ssa free segs: %bpu\n", prefix, emis->segs[4]);
erts_print(to, arg, "%ssua free segs: %bpu\n", prefix, emis->segs[5]);
}
- if (!mmap_state.no_os_mmap) {
+ if (!mm->no_os_mmap) {
erts_print(to, arg, "os mmap size used: %bpu\n", emis->os_used);
}
}
@@ -2377,7 +2393,7 @@ Eterm erts_mmap_info(int *print_to_p,
}
lix = 0;
- if (mmap_state.supercarrier) {
+ if (mm->supercarrier) {
group[0] = erts_bld_atom_uword_2tup_list(hpp, szp,
sizeof(size_tags)/sizeof(Eterm),
size_tags, emis->sizes);
@@ -2389,7 +2405,7 @@ Eterm erts_mmap_info(int *print_to_p,
lix++;
}
- if (!mmap_state.no_os_mmap) {
+ if (!mm->no_os_mmap) {
group[0] = erts_bld_atom_uword_2tup_list(hpp, szp,
1, &am.used, &emis->os_used);
list[lix] = erts_bld_2tup_list(hpp, szp, 1, group_tags, group);
@@ -2401,25 +2417,26 @@ Eterm erts_mmap_info(int *print_to_p,
return res;
}
-Eterm erts_mmap_info_options(char *prefix,
+Eterm erts_mmap_info_options(ErtsMemMapper* mm,
+ char *prefix,
int *print_to_p,
void *print_to_arg,
Uint **hpp,
Uint *szp)
{
- const UWord scs = mmap_state.sua.top - mmap_state.sa.bot;
- const Eterm sco = mmap_state.no_os_mmap ? am_true : am_false;
- const Eterm scrpm = (mmap_state.reserve_physical == reserve_noop) ? am_true : am_false;
+ const UWord scs = mm->sua.top - mm->sa.bot;
+ const Eterm sco = mm->no_os_mmap ? am_true : am_false;
+ const Eterm scrpm = (mm->reserve_physical == reserve_noop) ? am_true : am_false;
Eterm res = THE_NON_VALUE;
if (print_to_p) {
int to = *print_to_p;
void *arg = print_to_arg;
erts_print(to, arg, "%sscs: %bpu\n", prefix, scs);
- if (mmap_state.supercarrier) {
+ if (mm->supercarrier) {
erts_print(to, arg, "%ssco: %T\n", prefix, sco);
erts_print(to, arg, "%sscrpm: %T\n", prefix, scrpm);
- erts_print(to, arg, "%sscrfsd: %beu\n", prefix, mmap_state.desc.reserved);
+ erts_print(to, arg, "%sscrfsd: %beu\n", prefix, mm->desc.reserved);
}
}
@@ -2429,9 +2446,9 @@ Eterm erts_mmap_info_options(char *prefix,
}
res = NIL;
- if (mmap_state.supercarrier) {
+ if (mm->supercarrier) {
add_2tup(hpp, szp, &res, am.scrfsd,
- erts_bld_uint(hpp,szp, mmap_state.desc.reserved));
+ erts_bld_uint(hpp,szp, mm->desc.reserved));
add_2tup(hpp, szp, &res, am.scrpm, scrpm);
add_2tup(hpp, szp, &res, am.sco, sco);
}
@@ -2441,9 +2458,9 @@ Eterm erts_mmap_info_options(char *prefix,
}
-Eterm erts_mmap_debug_info(Process* p)
+Eterm erts_mmap_debug_info(ErtsMemMapper* mm, Process* p)
{
- if (mmap_state.supercarrier) {
+ if (mm->supercarrier) {
ERTS_DECL_AM(sabot);
ERTS_DECL_AM(satop);
ERTS_DECL_AM(suabot);
@@ -2454,14 +2471,14 @@ Eterm erts_mmap_debug_info(Process* p)
Eterm *hp, *hp_end;
Uint may_need;
- erts_smp_mtx_lock(&mmap_state.mtx);
- values[0] = (UWord)mmap_state.sa.bot;
- values[1] = (UWord)mmap_state.sa.top;
- values[2] = (UWord)mmap_state.sua.bot;
- values[3] = (UWord)mmap_state.sua.top;
- sa_list = build_free_seg_list(p, &mmap_state.sa.map);
- sua_list = build_free_seg_list(p, &mmap_state.sua.map);
- erts_smp_mtx_unlock(&mmap_state.mtx);
+ erts_smp_mtx_lock(&mm->mtx);
+ values[0] = (UWord)mm->sa.bot;
+ values[1] = (UWord)mm->sa.top;
+ values[2] = (UWord)mm->sua.bot;
+ values[3] = (UWord)mm->sua.top;
+ sa_list = build_free_seg_list(p, &mm->sa.map);
+ sua_list = build_free_seg_list(p, &mm->sua.map);
+ erts_smp_mtx_unlock(&mm->mtx);
may_need = 4*(2+3+2) + 2*(2+3);
hp = HAlloc(p, may_need);
diff --git a/erts/emulator/sys/common/erl_mmap.h b/erts/emulator/sys/common/erl_mmap.h
index 66619c5161..61d912fd28 100644
--- a/erts/emulator/sys/common/erl_mmap.h
+++ b/erts/emulator/sys/common/erl_mmap.h
@@ -30,9 +30,6 @@
#define ERTS_MMAPFLG_SUPERCARRIER_ONLY (((Uint32) 1) << 1)
#define ERTS_MMAPFLG_SUPERALIGNED (((Uint32) 1) << 2)
-#define ERTS_HAVE_ERTS_OS_MMAP (1 << 0)
-#define ERTS_HAVE_ERTS_SUPERCARRIER_MMAP (1 << 1)
-extern int erts_have_erts_mmap;
extern UWord erts_page_inv_mask;
typedef struct {
@@ -53,23 +50,29 @@ typedef struct {
#define ERTS_MMAP_INIT_DEFAULT_INITER \
{{NULL, NULL}, {NULL, NULL}, 0, 1, (1 << 16), 1}
-void *erts_mmap(Uint32 flags, UWord *sizep);
-void erts_munmap(Uint32 flags, void *ptr, UWord size);
-void *erts_mremap(Uint32 flags, void *ptr, UWord old_size, UWord *sizep);
-int erts_mmap_in_supercarrier(void *ptr);
-void erts_mmap_init(ErtsMMapInit*);
+#define ERTS_MMAP_INIT_LITERAL_INITER \
+ {{NULL, NULL}, {NULL, NULL}, 1024*1024*1024, 1, (1 << 16), 0}
+
+typedef struct ErtsMemMapper_ ErtsMemMapper;
+
+void *erts_mmap(ErtsMemMapper*, Uint32 flags, UWord *sizep);
+void erts_munmap(ErtsMemMapper*, Uint32 flags, void *ptr, UWord size);
+void *erts_mremap(ErtsMemMapper*, Uint32 flags, void *ptr, UWord old_size, UWord *sizep);
+int erts_mmap_in_supercarrier(ErtsMemMapper*, void *ptr);
+void erts_mmap_init(ErtsMemMapper*, ErtsMMapInit*);
struct erts_mmap_info_struct
{
UWord sizes[6];
UWord segs[6];
UWord os_used;
};
-Eterm erts_mmap_info(int *print_to_p, void *print_to_arg,
+Eterm erts_mmap_info(ErtsMemMapper*, int *print_to_p, void *print_to_arg,
Eterm** hpp, Uint* szp, struct erts_mmap_info_struct*);
-Eterm erts_mmap_info_options(char *prefix, int *print_to_p, void *print_to_arg,
+Eterm erts_mmap_info_options(ErtsMemMapper*,
+ char *prefix, int *print_to_p, void *print_to_arg,
Uint **hpp, Uint *szp);
struct process;
-Eterm erts_mmap_debug_info(struct process*);
+Eterm erts_mmap_debug_info(ErtsMemMapper*, struct process*);
#define ERTS_SUPERALIGNED_SIZE \
(1 << ERTS_MMAP_SUPERALIGNED_BITS)
@@ -121,6 +124,11 @@ Eterm erts_mmap_debug_info(struct process*);
# define ERTS_HAVE_OS_MMAP 1
#endif
+extern ErtsMemMapper erts_dflt_mmapper;
+#if defined(ARCH_64) && defined(ERTS_HAVE_OS_PHYSICAL_MEMORY_RESERVATION)
+extern ErtsMemMapper erts_literal_mmapper;
+#endif
+
/*#define HARD_DEBUG_MSEG*/
#ifdef HARD_DEBUG_MSEG
# define HARD_DBG_INSERT_MSEG hard_dbg_insert_mseg
diff --git a/erts/emulator/sys/common/erl_mseg.c b/erts/emulator/sys/common/erl_mseg.c
index 7eb8a4a460..20695899eb 100644
--- a/erts/emulator/sys/common/erl_mseg.c
+++ b/erts/emulator/sys/common/erl_mseg.c
@@ -291,7 +291,7 @@ mseg_create(ErtsMsegAllctr_t *ma, Uint flags, UWord *sizep)
if (MSEG_FLG_IS_2POW(flags))
mmap_flags |= ERTS_MMAPFLG_SUPERALIGNED;
- seg = erts_mmap(mmap_flags, sizep);
+ seg = erts_mmap(&erts_dflt_mmapper, mmap_flags, sizep);
#ifdef ERTS_PRINT_ERTS_MMAP
erts_fprintf(stderr, "%p = erts_mmap(%s, {%bpu, %bpu});\n", seg,
@@ -311,7 +311,7 @@ mseg_destroy(ErtsMsegAllctr_t *ma, Uint flags, void *seg_p, UWord size) {
if (MSEG_FLG_IS_2POW(flags))
mmap_flags |= ERTS_MMAPFLG_SUPERALIGNED;
- erts_munmap(mmap_flags, seg_p, size);
+ erts_munmap(&erts_dflt_mmapper, mmap_flags, seg_p, size);
#ifdef ERTS_PRINT_ERTS_MMAP
erts_fprintf(stderr, "erts_munmap(%s, %p, %bpu);\n",
(mmap_flags & ERTS_MMAPFLG_SUPERALIGNED) ? "sa" : "sua",
@@ -332,7 +332,7 @@ mseg_recreate(ErtsMsegAllctr_t *ma, Uint flags, void *old_seg, UWord old_size, U
if (MSEG_FLG_IS_2POW(flags))
mmap_flags |= ERTS_MMAPFLG_SUPERALIGNED;
- new_seg = erts_mremap(mmap_flags, old_seg, old_size, sizep);
+ new_seg = erts_mremap(&erts_dflt_mmapper, mmap_flags, old_seg, old_size, sizep);
#ifdef ERTS_PRINT_ERTS_MMAP
erts_fprintf(stderr, "%p = erts_mremap(%s, %p, %bpu, {%bpu, %bpu});\n",
@@ -997,7 +997,8 @@ info_options(ErtsMsegAllctr_t *ma,
{
Eterm res;
- res = erts_mmap_info_options(prefix, print_to_p, print_to_arg, hpp, szp);
+ res = erts_mmap_info_options(&erts_dflt_mmapper,
+ prefix, print_to_p, print_to_arg, hpp, szp);
if (print_to_p) {
int to = *print_to_p;
@@ -1401,7 +1402,7 @@ erts_mseg_init(ErtsMsegInit_t *init)
erts_mtx_init(&init_atoms_mutex, "mseg_init_atoms");
- erts_mmap_init(&init->mmap);
+ erts_mmap_init(&erts_dflt_mmapper, &init->dflt_mmap);
if (!IS_2POW(GET_PAGE_SIZE))
erl_exit(ERTS_ABORT_EXIT, "erts_mseg: Unexpected page_size %beu\n", GET_PAGE_SIZE);
diff --git a/erts/emulator/sys/common/erl_mseg.h b/erts/emulator/sys/common/erl_mseg.h
index 656484702d..2acd8f8505 100644
--- a/erts/emulator/sys/common/erl_mseg.h
+++ b/erts/emulator/sys/common/erl_mseg.h
@@ -42,16 +42,6 @@
#if ERTS_HAVE_MSEG_SUPER_ALIGNED
# define MSEG_ALIGN_BITS ERTS_MMAP_SUPERALIGNED_BITS
-#else
-/* If we don't use super aligned multiblock carriers
- * we will mmap with page size alignment (and thus use corresponding
- * align bits).
- *
- * Current implementation needs this to be a constant and
- * only uses this for user dev testing so setting page size
- * to 4096 (12 bits) is fine.
- */
-# define MSEG_ALIGN_BITS (12)
#endif
#if HAVE_ERTS_MSEG
@@ -69,7 +59,8 @@ typedef struct {
Uint rmcbf;
Uint mcs;
Uint nos;
- ErtsMMapInit mmap;
+ ErtsMMapInit dflt_mmap;
+ ErtsMMapInit literal_mmap;
} ErtsMsegInit_t;
#define ERTS_MSEG_INIT_DEFAULT_INITIALIZER \
@@ -78,7 +69,8 @@ typedef struct {
20, /* rmcbf: Relative max cache bad fit */ \
10, /* mcs: Max cache size */ \
1000, /* cci: Cache check interval */ \
- ERTS_MMAP_INIT_DEFAULT_INITER \
+ ERTS_MMAP_INIT_DEFAULT_INITER, \
+ ERTS_MMAP_INIT_LITERAL_INITER \
}
typedef struct {
diff --git a/erts/emulator/sys/common/erl_poll.h b/erts/emulator/sys/common/erl_poll.h
index 6d8aef822e..bc2c681876 100644
--- a/erts/emulator/sys/common/erl_poll.h
+++ b/erts/emulator/sys/common/erl_poll.h
@@ -122,7 +122,7 @@ typedef Uint32 ErtsPollEvents;
#endif
#define ERTS_POLL_EV_E2N(EV) \
- ((__uint32_t) (EV))
+ ((uint32_t) (EV))
#define ERTS_POLL_EV_N2E(EV) \
((ErtsPollEvents) (EV))
diff --git a/erts/emulator/sys/win32/erl_win32_sys_ddll.c b/erts/emulator/sys/win32/erl_win32_sys_ddll.c
index 9a5557e93d..7c24a77e31 100644
--- a/erts/emulator/sys/win32/erl_win32_sys_ddll.c
+++ b/erts/emulator/sys/win32/erl_win32_sys_ddll.c
@@ -52,7 +52,8 @@ void erl_sys_ddll_init(void) {
#define ERL_NIF_API_FUNC_DECL(RET,NAME,ARGS) nif_callbacks.NAME = NAME
#include "erl_nif_api_funcs.h"
#undef ERL_NIF_API_FUNC_DECL
-
+ nif_callbacks.erts_alc_test = erts_alc_test;
+
return;
}
diff --git a/erts/emulator/sys/win32/erl_win_dyn_driver.h b/erts/emulator/sys/win32/erl_win_dyn_driver.h
index 5e62320be4..baac7c903e 100644
--- a/erts/emulator/sys/win32/erl_win_dyn_driver.h
+++ b/erts/emulator/sys/win32/erl_win_dyn_driver.h
@@ -145,8 +145,8 @@ WDD_TYPEDEF(ErlDrvTid, erl_drv_thread_self, (void));
WDD_TYPEDEF(int, erl_drv_equal_tids, (ErlDrvTid tid1, ErlDrvTid tid2));
WDD_TYPEDEF(void, erl_drv_thread_exit, (void *resp));
WDD_TYPEDEF(int, erl_drv_thread_join, (ErlDrvTid, void **respp));
-WDD_TYPEDEF(int, erl_drv_putenv, (char *key, char *value));
-WDD_TYPEDEF(int, erl_drv_getenv, (char *key, char *value, size_t *value_size));
+WDD_TYPEDEF(int, erl_drv_putenv, (const char *key, char *value));
+WDD_TYPEDEF(int, erl_drv_getenv, (const char *key, char *value, size_t *value_size));
typedef struct {
WDD_FTYPE(null_func) *null_func;
diff --git a/erts/emulator/test/Makefile b/erts/emulator/test/Makefile
index 77614d455c..8cc47937b7 100644
--- a/erts/emulator/test/Makefile
+++ b/erts/emulator/test/Makefile
@@ -79,6 +79,7 @@ MODULES= \
node_container_SUITE \
nofrag_SUITE \
num_bif_SUITE \
+ message_queue_data_SUITE \
op_SUITE \
port_SUITE \
port_bif_SUITE \
diff --git a/erts/emulator/test/alloc_SUITE.erl b/erts/emulator/test/alloc_SUITE.erl
index 3ad1b88b2d..516bc873a5 100644
--- a/erts/emulator/test/alloc_SUITE.erl
+++ b/erts/emulator/test/alloc_SUITE.erl
@@ -31,7 +31,8 @@
rbtree/1,
mseg_clear_cache/1,
erts_mmap/1,
- cpool/1]).
+ cpool/1,
+ migration/1]).
-export([init_per_testcase/2, end_per_testcase/2]).
@@ -43,7 +44,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[basic, coalesce, threads, realloc_copy, bucket_index,
- bucket_mask, rbtree, mseg_clear_cache, erts_mmap, cpool].
+ bucket_mask, rbtree, mseg_clear_cache, erts_mmap, cpool, migration].
groups() ->
[].
@@ -64,7 +65,7 @@ end_per_group(_GroupName, Config) ->
init_per_testcase(Case, Config) when is_list(Config) ->
Dog = ?t:timetrap(?t:seconds(?DEFAULT_TIMETRAP_SECS)),
- [{watchdog, Dog},{testcase, Case}|Config].
+ [{watchdog, Dog}, {testcase, Case}, {debug,false} | Config].
end_per_testcase(_Case, Config) when is_list(Config) ->
Dog = ?config(watchdog, Config),
@@ -112,6 +113,14 @@ cpool(suite) -> [];
cpool(doc) -> [];
cpool(Cfg) -> ?line drv_case(Cfg).
+migration(Cfg) ->
+ case erlang:system_info(smp_support) of
+ true ->
+ drv_case(Cfg, concurrent, "+MZe true");
+ false ->
+ {skipped, "No smp"}
+ end.
+
erts_mmap(Config) when is_list(Config) ->
case ?t:os_type() of
{unix, _} ->
@@ -173,18 +182,17 @@ erts_mmap_do(Config, SCO, SCRPM, SCRFSD) ->
%% %%
drv_case(Config) ->
- drv_case(Config, "").
+ drv_case(Config, one_shot, "").
-drv_case(Config, Command) when is_list(Config),
- is_list(Command) ->
+drv_case(Config, Mode, NodeOpts) when is_list(Config) ->
case ?t:os_type() of
{Family, _} when Family == unix; Family == win32 ->
- ?line {ok, Node} = start_node(Config),
+ ?line {ok, Node} = start_node(Config, NodeOpts),
?line Self = self(),
?line Ref = make_ref(),
?line spawn_link(Node,
fun () ->
- Res = run_drv_case(Config, Command),
+ Res = run_drv_case(Config, Mode),
Self ! {Ref, Res}
end),
?line Result = receive {Ref, Rslt} -> Rslt end,
@@ -196,49 +204,172 @@ drv_case(Config, Command) when is_list(Config),
| io_lib:format("~p",[SkipOs])])}
end.
-run_drv_case(Config, Command) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line CaseName = ?config(testcase,Config),
- case erl_ddll:load_driver(DataDir, CaseName) of
- ok -> ok;
- {error, Error} ->
- io:format("~s\n", [erl_ddll:format_error(Error)]),
- ?line ?t:fail()
+run_drv_case(Config, Mode) ->
+ DataDir = ?config(data_dir,Config),
+ CaseName = ?config(testcase,Config),
+ File = filename:join(DataDir, CaseName),
+ {ok,CaseName,Bin} = compile:file(File, [binary,return_errors]),
+ {module,CaseName} = erlang:load_module(CaseName,Bin),
+ print_stats(CaseName),
+ ok = CaseName:init(File),
+
+ SlaveState = slave_init(CaseName),
+ case Mode of
+ one_shot ->
+ Result = one_shot(CaseName);
+
+ concurrent ->
+ Result = concurrent(CaseName)
end,
- ?line Port = open_port({spawn, atom_to_list(CaseName)}, []),
- ?line true = is_port(Port),
- ?line Port ! {self(), {command, Command}},
- ?line Result = receive_drv_result(Port, CaseName),
- ?line Port ! {self(), close},
- ?line receive
- {Port, closed} ->
- ok
- end,
- ?line ok = erl_ddll:unload_driver(CaseName),
- ?line Result.
-
-receive_drv_result(Port, CaseName) ->
- ?line receive
- {print, Port, CaseName, Str} ->
- ?line ?t:format("~s", [Str]),
- ?line receive_drv_result(Port, CaseName);
- {'EXIT', Port, Error} ->
- ?line ?t:fail(Error);
- {'EXIT', error, Error} ->
- ?line ?t:fail(Error);
- {failed, Port, CaseName, Comment} ->
- ?line ?t:fail(Comment);
- {skipped, Port, CaseName, Comment} ->
- ?line {skipped, Comment};
- {succeeded, Port, CaseName, ""} ->
- ?line succeeded;
- {succeeded, Port, CaseName, Comment} ->
- ?line {comment, Comment}
- end.
-
-start_node(Config) ->
- start_node(Config, []).
+
+ wait_for_memory_deallocations(),
+ print_stats(CaseName),
+
+ true = erlang:delete_module(CaseName),
+ slave_end(SlaveState),
+ Result.
+
+slave_init(migration) ->
+ A0 = case application:start(sasl) of
+ ok -> [sasl];
+ _ -> []
+ end,
+ case application:start(os_mon) of
+ ok -> [os_mon|A0];
+ _ -> A0
+ end;
+slave_init(_) -> [].
+
+slave_end(Apps) ->
+ lists:foreach(fun (A) -> application:stop(A) end, Apps).
+
+wait_for_memory_deallocations() ->
+ try
+ erts_debug:set_internal_state(wait, deallocations)
+ catch
+ error:undef ->
+ erts_debug:set_internal_state(available_internal_state, true),
+ wait_for_memory_deallocations()
+ end.
+
+print_stats(migration) ->
+ {Btot,Ctot} = lists:foldl(fun({instance,Inr,Istats}, {Bacc,Cacc}) ->
+ {mbcs,MBCS} = lists:keyfind(mbcs, 1, Istats),
+ Btup = lists:keyfind(blocks, 1, MBCS),
+ Ctup = lists:keyfind(carriers, 1, MBCS),
+ io:format("{instance,~p,~p,~p}\n", [Inr, Btup, Ctup]),
+ {tuple_add(Bacc,Btup),tuple_add(Cacc,Ctup)};
+ (_, Acc) -> Acc
+ end,
+ {{blocks,0,0,0},{carriers,0,0,0}},
+ erlang:system_info({allocator,test_alloc})),
+
+ io:format("Number of blocks : ~p\n", [Btot]),
+ io:format("Number of carriers: ~p\n", [Ctot]);
+
+print_stats(_) -> ok.
+
+tuple_add(T1, T2) ->
+ list_to_tuple(lists:zipwith(fun(E1,E2) when is_number(E1), is_number(E2) ->
+ E1 + E2;
+ (A,A) ->
+ A
+ end,
+ tuple_to_list(T1), tuple_to_list(T2))).
+
+
+one_shot(CaseName) ->
+ State = CaseName:start({1, 0, erlang:system_info(build_type)}),
+ Result0 = CaseName:run(State),
+ false = (Result0 =:= continue),
+ Result1 = handle_result(State, Result0),
+ CaseName:stop(State),
+ Result1.
+
+
+many_shot(CaseName, I, Mem) ->
+ State = CaseName:start({I, Mem, erlang:system_info(build_type)}),
+ Result1 = repeat_while(fun() ->
+ Result0 = CaseName:run(State),
+ handle_result(State, Result0)
+ end,
+ 10*1000, I),
+ CaseName:stop(State),
+ flush_log(),
+ Result1.
+
+concurrent(CaseName) ->
+ NSched = erlang:system_info(schedulers),
+ Mem = (free_memory() * 3) div 4,
+ PRs = lists:map(fun(I) -> spawn_opt(fun() ->
+ many_shot(CaseName, I,
+ Mem div NSched)
+ end,
+ [monitor, {scheduler,I}])
+ end,
+ lists:seq(1, NSched)),
+ lists:foreach(fun({Pid,Ref}) ->
+ receive {'DOWN', Ref, process, Pid, Reason} ->
+ Reason
+ end
+ end,
+ PRs),
+ ok.
+
+repeat_while(Fun, Timeout, I) ->
+ TRef = erlang:start_timer(Timeout, self(), timeout),
+ R = repeat_while_loop(Fun, TRef, I),
+ erlang:cancel_timer(TRef, [{async,true},{info,false}]),
+ R.
+
+repeat_while_loop(Fun, TRef, I) ->
+ receive
+ {timeout, TRef, timeout} ->
+ io:format("~p: Timeout, enough is enough.",[I]),
+ succeeded
+ after 0 ->
+ %%io:format("~p calls fun\n", [self()]),
+ case Fun() of
+ continue -> repeat_while_loop(Fun, TRef, I);
+ R -> R
+ end
+ end.
+
+flush_log() ->
+ receive
+ {print, Str} ->
+ ?t:format("~s", [Str]),
+ flush_log()
+ after 0 ->
+ ok
+ end.
+
+handle_result(_State, Result0) ->
+ flush_log(),
+ case Result0 of
+ {'EXIT', Error} ->
+ ?line ?t:fail(Error);
+ {'EXIT', error, Error} ->
+ ?line ?t:fail(Error);
+ {failed, Comment} ->
+ ?line ?t:fail(Comment);
+ {skipped, Comment} ->
+ ?line {skipped, Comment};
+ {succeeded, ""} ->
+ ?line succeeded;
+ {succeeded, Comment} ->
+ ?line {comment, Comment};
+ continue ->
+ continue
+ end.
+
start_node(Config, Opts) when is_list(Config), is_list(Opts) ->
+ case ?config(debug,Config) of
+ true -> {ok, node()};
+ _ -> start_node_1(Config, Opts)
+ end.
+
+start_node_1(Config, Opts) ->
Pa = filename:dirname(code:which(?MODULE)),
Name = list_to_atom(atom_to_list(?MODULE)
++ "-"
@@ -249,5 +380,27 @@ start_node(Config, Opts) when is_list(Config), is_list(Opts) ->
++ integer_to_list(erlang:unique_integer([positive]))),
?t:start_node(Name, slave, [{args, Opts++" -pa "++Pa}]).
+stop_node(Node) when Node =:= node() -> ok;
stop_node(Node) ->
?t:stop_node(Node).
+
+free_memory() ->
+ %% Free memory in MB.
+ try
+ SMD = memsup:get_system_memory_data(),
+ {value, {free_memory, Free}} = lists:keysearch(free_memory, 1, SMD),
+ TotFree = (Free +
+ case lists:keysearch(cached_memory, 1, SMD) of
+ {value, {cached_memory, Cached}} -> Cached;
+ false -> 0
+ end +
+ case lists:keysearch(buffered_memory, 1, SMD) of
+ {value, {buffered_memory, Buffed}} -> Buffed;
+ false -> 0
+ end),
+ TotFree div (1024*1024)
+ catch
+ error : undef ->
+ ?t:fail({"os_mon not built"})
+ end.
+
diff --git a/erts/emulator/test/alloc_SUITE_data/Makefile.src b/erts/emulator/test/alloc_SUITE_data/Makefile.src
index a441fe946b..e31de54e1b 100644
--- a/erts/emulator/test/alloc_SUITE_data/Makefile.src
+++ b/erts/emulator/test/alloc_SUITE_data/Makefile.src
@@ -25,7 +25,8 @@ TEST_DRVS = basic@dll@ \
bucket_mask@dll@ \
rbtree@dll@ \
mseg_clear_cache@dll@ \
- cpool@dll@
+ cpool@dll@ \
+ migration@dll@
CC = @CC@
LD = @LD@
diff --git a/erts/emulator/test/alloc_SUITE_data/allocator_test.h b/erts/emulator/test/alloc_SUITE_data/allocator_test.h
index 1d6b2f4907..97ee58cdad 100644
--- a/erts/emulator/test/alloc_SUITE_data/allocator_test.h
+++ b/erts/emulator/test/alloc_SUITE_data/allocator_test.h
@@ -20,9 +20,20 @@
#ifndef ALLOCATOR_TEST_H__
#define ALLOCATOR_TEST_H__
-typedef ErlDrvUInt Ulong;
+#if SIZEOF_VOID_P == SIZEOF_INT
+typedef unsigned int Ulong;
+#elif SIZEOF_VOID_P == SIZEOF_LONG
+typedef unsigned long Ulong;
+#elif SIZEOF_VOID_P == SIZEOF_LONG_LONG
+typedef unsigned long long Ulong;
+#else
+# error No pointer sized integer type found ???
+#endif
-#ifndef __WIN32__
+#ifdef __WIN32__
+typedef Ulong erts_alc_test_Fn(Ulong, Ulong, Ulong, Ulong);
+# define erts_alc_test ((erts_alc_test_Fn*)WinDynNifCallbacks.erts_alc_test)
+#else
Ulong erts_alc_test(Ulong, Ulong, Ulong, Ulong);
#endif
@@ -85,6 +96,7 @@ typedef void* erts_cond;
#define CPOOL_DELETE(A,B) ((Carrier_t *) ALC_TEST2(0x022, (A), (B)))
#define CPOOL_IS_EMPTY(A) ((int) ALC_TEST1(0x023, (A)))
#define CPOOL_IS_IN_POOL(A,B) ((int) ALC_TEST2(0x024, (A), (B)))
+#define UMEM2BLK_TEST(P) ((Block_t*) ALC_TEST1(0x025, (P)))
/* From erl_goodfit_alloc.c */
#define BKT_IX(A, S) ((Ulong) ALC_TEST2(0x100, (A), (S)))
@@ -142,5 +154,9 @@ typedef void* erts_cond;
#define THR_JOIN(T) ((void) ALC_TEST1(0xf11, (T)))
#define THR_EXIT(R) ((void) ALC_TEST1(0xf12, (R)))
#define IS_SMP_ENABLED ((int) ALC_TEST0(0xf13))
+#define ALLOC_TEST(S) ((void*) ALC_TEST1(0xf14, (S)))
+#define FREE_TEST(P) ((void) ALC_TEST1(0xf15, (P)))
+#define SET_TEST_MBC_USER_HEADER(SZ,CMBC,DMBC) ((int)ALC_TEST3(0xf16, (SZ), (CMBC), (DMBC)))
+#define GET_TEST_MBC_SIZE() ((int) ALC_TEST0(0xf17))
#endif
diff --git a/erts/emulator/test/alloc_SUITE_data/basic.c b/erts/emulator/test/alloc_SUITE_data/basic.c
index 323a24a11f..debb3d7ebe 100644
--- a/erts/emulator/test/alloc_SUITE_data/basic.c
+++ b/erts/emulator/test/alloc_SUITE_data/basic.c
@@ -60,3 +60,6 @@ testcase_cleanup(TestCaseState_t *tcs)
if (tcs->extra)
STOP_ALC((Allctr_t *) tcs->extra);
}
+
+ERL_NIF_INIT(basic, testcase_nif_funcs, testcase_nif_init,
+ NULL, NULL, NULL);
diff --git a/erts/emulator/test/alloc_SUITE_data/basic.erl b/erts/emulator/test/alloc_SUITE_data/basic.erl
new file mode 100644
index 0000000000..a018fd5582
--- /dev/null
+++ b/erts/emulator/test/alloc_SUITE_data/basic.erl
@@ -0,0 +1,10 @@
+-module(basic).
+
+-export([init/1, start/1, run/1, stop/1]).
+
+init(File) ->
+ ok = erlang:load_nif(File, 0).
+
+start(_) -> erlang:nif_error(not_loaded).
+run(_) -> erlang:nif_error(not_loaded).
+stop(_) -> erlang:nif_error(not_loaded).
diff --git a/erts/emulator/test/alloc_SUITE_data/bucket_index.c b/erts/emulator/test/alloc_SUITE_data/bucket_index.c
index c13f229049..45cb53fbf7 100644
--- a/erts/emulator/test/alloc_SUITE_data/bucket_index.c
+++ b/erts/emulator/test/alloc_SUITE_data/bucket_index.c
@@ -113,3 +113,5 @@ test_it(TestCaseState_t *tcs, unsigned sbct)
sbct ? sbct_buf : "default");
}
+ERL_NIF_INIT(bucket_index, testcase_nif_funcs, testcase_nif_init,
+ NULL, NULL, NULL);
diff --git a/erts/emulator/test/alloc_SUITE_data/bucket_index.erl b/erts/emulator/test/alloc_SUITE_data/bucket_index.erl
new file mode 100644
index 0000000000..c54f54e2f5
--- /dev/null
+++ b/erts/emulator/test/alloc_SUITE_data/bucket_index.erl
@@ -0,0 +1,10 @@
+-module(bucket_index).
+
+-export([init/1, start/1, run/1, stop/1]).
+
+init(File) ->
+ ok = erlang:load_nif(File, 0).
+
+start(_) -> erlang:nif_error(not_loaded).
+run(_) -> erlang:nif_error(not_loaded).
+stop(_) -> erlang:nif_error(not_loaded).
diff --git a/erts/emulator/test/alloc_SUITE_data/bucket_mask.c b/erts/emulator/test/alloc_SUITE_data/bucket_mask.c
index 8d6166771e..c94c265f4e 100644
--- a/erts/emulator/test/alloc_SUITE_data/bucket_mask.c
+++ b/erts/emulator/test/alloc_SUITE_data/bucket_mask.c
@@ -52,7 +52,7 @@ testcase_run(TestCaseState_t *tcs)
typedef struct linked_block {
struct linked_block* next;
}Linked;
- Linked* link;
+ Linked* link = NULL;
Linked* fence_list;
Linked* pad_list;
void* tmp;
@@ -183,3 +183,5 @@ testcase_run(TestCaseState_t *tcs)
tcs->extra = NULL;
}
+ERL_NIF_INIT(bucket_mask, testcase_nif_funcs, testcase_nif_init,
+ NULL, NULL, NULL);
diff --git a/erts/emulator/test/alloc_SUITE_data/bucket_mask.erl b/erts/emulator/test/alloc_SUITE_data/bucket_mask.erl
new file mode 100644
index 0000000000..589a50e1fa
--- /dev/null
+++ b/erts/emulator/test/alloc_SUITE_data/bucket_mask.erl
@@ -0,0 +1,10 @@
+-module(bucket_mask).
+
+-export([init/1, start/1, run/1, stop/1]).
+
+init(File) ->
+ ok = erlang:load_nif(File, 0).
+
+start(_) -> erlang:nif_error(not_loaded).
+run(_) -> erlang:nif_error(not_loaded).
+stop(_) -> erlang:nif_error(not_loaded).
diff --git a/erts/emulator/test/alloc_SUITE_data/coalesce.c b/erts/emulator/test/alloc_SUITE_data/coalesce.c
index 0a5e0c5b0e..7791409a34 100644
--- a/erts/emulator/test/alloc_SUITE_data/coalesce.c
+++ b/erts/emulator/test/alloc_SUITE_data/coalesce.c
@@ -317,3 +317,6 @@ testcase_cleanup(TestCaseState_t *tcs)
if (tcs->extra)
STOP_ALC((Allctr_t *) tcs->extra);
}
+
+ERL_NIF_INIT(coalesce, testcase_nif_funcs, testcase_nif_init,
+ NULL, NULL, NULL);
diff --git a/erts/emulator/test/alloc_SUITE_data/coalesce.erl b/erts/emulator/test/alloc_SUITE_data/coalesce.erl
new file mode 100644
index 0000000000..453c726c4e
--- /dev/null
+++ b/erts/emulator/test/alloc_SUITE_data/coalesce.erl
@@ -0,0 +1,10 @@
+-module(coalesce).
+
+-export([init/1, start/1, run/1, stop/1]).
+
+init(File) ->
+ ok = erlang:load_nif(File, 0).
+
+start(_) -> erlang:nif_error(not_loaded).
+run(_) -> erlang:nif_error(not_loaded).
+stop(_) -> erlang:nif_error(not_loaded).
diff --git a/erts/emulator/test/alloc_SUITE_data/cpool.c b/erts/emulator/test/alloc_SUITE_data/cpool.c
index 75c2bc13ae..73026cc758 100644
--- a/erts/emulator/test/alloc_SUITE_data/cpool.c
+++ b/erts/emulator/test/alloc_SUITE_data/cpool.c
@@ -86,13 +86,13 @@ thread_func(void *arg)
for (i = 0; i < (TEST_NO_CARRIERS_PER_THREAD+TEST_CARRIERS_OFFSET); i++) {
int d;
if (i < TEST_NO_CARRIERS_PER_THREAD) {
- CPOOL_INSERT(alloc, crr[i]);
+ (void) CPOOL_INSERT(alloc, crr[i]);
if ((i & 0x7) == 0)
FATAL_ASSERT(CPOOL_IS_IN_POOL(alloc, crr[i]));
}
d = i-TEST_CARRIERS_OFFSET;
if (d >= 0) {
- CPOOL_DELETE(alloc, crr[d]);
+ (void) CPOOL_DELETE(alloc, crr[d]);
if ((d & 0x7) == 0)
FATAL_ASSERT(!CPOOL_IS_IN_POOL(alloc, crr[d]));
}
@@ -129,7 +129,7 @@ testcase_run(TestCaseState_t *tcs)
for (c = 0; c < TEST_NO_CARRIERS_PER_THREAD; c++) {
Carrier_t *crr = (Carrier_t *) p;
p += zcrr_sz;
- ZERO_CRR_INIT(alloc, crr);
+ (void) ZERO_CRR_INIT(alloc, crr);
threads[t].crr[c] = crr;
}
}
@@ -156,3 +156,6 @@ testcase_run(TestCaseState_t *tcs)
ASSERT(tcs, no_threads == TEST_NO_THREADS);
}
+
+ERL_NIF_INIT(cpool, testcase_nif_funcs, testcase_nif_init,
+ NULL, NULL, NULL);
diff --git a/erts/emulator/test/alloc_SUITE_data/cpool.erl b/erts/emulator/test/alloc_SUITE_data/cpool.erl
new file mode 100644
index 0000000000..89053471fa
--- /dev/null
+++ b/erts/emulator/test/alloc_SUITE_data/cpool.erl
@@ -0,0 +1,10 @@
+-module(cpool).
+
+-export([init/1, start/1, run/1, stop/1]).
+
+init(File) ->
+ ok = erlang:load_nif(File, 0).
+
+start(_) -> erlang:nif_error(not_loaded).
+run(_) -> erlang:nif_error(not_loaded).
+stop(_) -> erlang:nif_error(not_loaded).
diff --git a/erts/emulator/test/alloc_SUITE_data/migration.c b/erts/emulator/test/alloc_SUITE_data/migration.c
new file mode 100644
index 0000000000..b006360043
--- /dev/null
+++ b/erts/emulator/test/alloc_SUITE_data/migration.c
@@ -0,0 +1,343 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2014. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ * Test the carrier migration logic
+ */
+
+#ifndef __WIN32__
+#include <sys/types.h>
+#include <unistd.h>
+#include <errno.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include "testcase_driver.h"
+#include "allocator_test.h"
+
+#define FATAL_ASSERT(A) \
+ ((void) ((A) \
+ ? 1 \
+ : (fatal_assert_failed(#A, \
+ (char *) __FILE__, \
+ __LINE__), \
+ 0)))
+
+static void
+fatal_assert_failed(char* expr, char* file, int line)
+{
+ fflush(stdout);
+ fprintf(stderr, "%s:%d: Assertion failed: %s\n",
+ file, line, expr);
+ fflush(stderr);
+ abort();
+}
+
+
+char *
+testcase_name(void)
+{
+ return "migration";
+}
+
+/* Turns out random_r() is a nonstandard glibc extension.
+#define HAVE_RANDOM_R
+*/
+#ifdef HAVE_RANDOM_R
+
+typedef struct { struct random_data rnd; char rndbuf[32]; } MyRandState;
+
+static void myrand_init(MyRandState* mrs, unsigned int seed)
+{
+ int res;
+ memset(&mrs->rnd, 0, sizeof(mrs->rnd));
+ res = initstate_r(seed, mrs->rndbuf, sizeof(mrs->rndbuf), &mrs->rnd);
+ FATAL_ASSERT(res == 0);
+}
+
+static int myrand(MyRandState* mrs)
+{
+ int32_t x;
+ int res = random_r(&mrs->rnd, &x);
+ FATAL_ASSERT(res == 0);
+ return (int)x;
+}
+
+#else /* !HAVE_RANDOM_R */
+
+typedef unsigned int MyRandState;
+
+static void myrand_init(MyRandState* mrs, unsigned int seed)
+{
+ *mrs = seed;
+}
+
+static int myrand(MyRandState* mrs)
+{
+ /* Taken from rand(3) man page.
+ * Modified to return a full 31-bit value by using low half of *mrs as well.
+ */
+ *mrs = (*mrs) * 1103515245 + 12345;
+ return (int) (((*mrs >> 16) | (*mrs << 16)) & ~(1 << 31));
+}
+
+#endif /* !HAVE_RANDOM_R */
+
+#define MAX_BLOCK_PER_THR 200
+#define BLOCKS_PER_MBC 10
+#define MAX_ROUNDS 10000
+
+typedef struct MyBlock_ {
+ struct MyBlock_* next;
+ struct MyBlock_** prevp;
+} MyBlock;
+
+typedef struct {
+ MyBlock* blockv[MAX_BLOCK_PER_THR];
+ MyRandState rand_state;
+ enum { GROWING, SHRINKING, CLEANUP, DONE } phase;
+ int nblocks;
+ int goal_nblocks;
+ int round;
+ int nr_of_migrations;
+ int nr_of_carriers;
+ int max_blocks_in_mbc;
+ int block_size;
+ int max_nblocks;
+} MigrationState;
+
+typedef struct {
+ ErlNifMutex* mtx;
+ int nblocks;
+ MyBlock* first;
+ MigrationState* employer;
+} MyCrrInfo;
+
+
+static int crr_info_offset = -1;
+static void (*orig_create_mbc_fn)(Allctr_t *allctr, Carrier_t *carrier);
+static void (*orig_destroying_mbc_fn)(Allctr_t *allctr, Carrier_t *carrier);
+
+static void my_creating_mbc(Allctr_t *allctr, Carrier_t *carrier)
+{
+ MyCrrInfo* mci = (MyCrrInfo*) ((char*)carrier + crr_info_offset);
+ if (orig_create_mbc_fn)
+ orig_create_mbc_fn(allctr, carrier);
+
+ mci->mtx = enif_mutex_create("alloc_SUITE.migration");
+ mci->nblocks = 0;
+ mci->first = NULL;
+ mci->employer = NULL;
+}
+
+static void my_destroying_mbc(Allctr_t *allctr, Carrier_t *carrier)
+{
+ MyCrrInfo* mci = (MyCrrInfo*) ((char*)carrier + crr_info_offset);
+
+ FATAL_ASSERT(mci->nblocks == 0);
+ FATAL_ASSERT(mci->first == NULL);
+ enif_mutex_destroy(mci->mtx);
+
+ if (orig_destroying_mbc_fn)
+ orig_destroying_mbc_fn(allctr, carrier);
+}
+
+static int migration_init(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
+{
+ void* creating_mbc_arg = (void*)my_creating_mbc;
+ void* destroying_mbc_arg = (void*)my_destroying_mbc;
+
+ if (testcase_nif_init(env, priv_data, load_info))
+ return -1;
+
+ crr_info_offset = SET_TEST_MBC_USER_HEADER(sizeof(MyCrrInfo),
+ &creating_mbc_arg,
+ &destroying_mbc_arg);
+ FATAL_ASSERT(crr_info_offset >= 0);
+ orig_create_mbc_fn = creating_mbc_arg;
+ orig_destroying_mbc_fn = destroying_mbc_arg;
+
+ return 0;
+}
+
+static void add_block(MyBlock* p, MigrationState* state)
+{
+ MyCrrInfo* mci = (MyCrrInfo*)((char*)BLK_TO_MBC(UMEM2BLK_TEST(p)) + crr_info_offset);
+
+ enif_mutex_lock(mci->mtx);
+ if (++mci->nblocks > state->max_blocks_in_mbc)
+ state->max_blocks_in_mbc = mci->nblocks;
+ p->next = mci->first;
+ p->prevp = &mci->first;
+ mci->first = p;
+ if (p->next)
+ p->next->prevp = &p->next;
+ if (mci->employer != state) {
+ if (!mci->employer) {
+ FATAL_ASSERT(mci->nblocks == 1);
+ state->nr_of_carriers++;
+ }
+ else {
+ state->nr_of_migrations++;
+ }
+ mci->employer = state;
+ }
+ enif_mutex_unlock(mci->mtx);
+}
+
+static void remove_block(MyBlock* p)
+{
+ MyCrrInfo* mci = (MyCrrInfo*)((char*)BLK_TO_MBC(UMEM2BLK_TEST(p)) + crr_info_offset);
+
+ enif_mutex_lock(mci->mtx);
+ mci->nblocks--;
+ if (p->next)
+ p->next->prevp = p->prevp;
+ *p->prevp = p->next;
+ enif_mutex_unlock(mci->mtx);
+}
+
+static int rand_int(MigrationState* state, int low, int high)
+{
+ int x;
+ FATAL_ASSERT(high >= low);
+ x = myrand(&state->rand_state);
+ return low + (x % (high+1-low));
+}
+
+
+static void do_cleanup(TestCaseState_t *tcs, MigrationState* state)
+{
+ if (state->nblocks == 0) {
+ state->phase = DONE;
+ testcase_printf(tcs, "%d: Done %d rounds", tcs->thr_nr, state->round);
+ testcase_printf(tcs, "%d: Cleanup all blocks", tcs->thr_nr);
+ testcase_printf(tcs, "%d: Empty carriers detected = %d", tcs->thr_nr,
+ state->nr_of_carriers);
+ testcase_printf(tcs, "%d: Migrations detected = %d", tcs->thr_nr,
+ state->nr_of_migrations);
+ testcase_printf(tcs, "%d: Max blocks in carrier = %d", tcs->thr_nr,
+ state->max_blocks_in_mbc);
+ }
+ else {
+ state->nblocks--;
+ if (state->blockv[state->nblocks]) {
+ remove_block(state->blockv[state->nblocks]);
+ FREE_TEST(state->blockv[state->nblocks]);
+ }
+ }
+}
+
+
+void
+testcase_run(TestCaseState_t *tcs)
+{
+ MigrationState* state = (MigrationState*) tcs->extra;
+
+ if (!tcs->extra) {
+ if (!IS_SMP_ENABLED)
+ testcase_skipped(tcs, "No SMP support");
+
+ tcs->extra = enif_alloc(sizeof(MigrationState));
+ state = (MigrationState*) tcs->extra;
+ memset(state->blockv, 0, sizeof(state->blockv));
+ myrand_init(&state->rand_state, tcs->thr_nr);
+ state->phase = GROWING;
+ state->nblocks = 0;
+ state->round = 0;
+ state->nr_of_migrations = 0;
+ state->nr_of_carriers = 0;
+ state->max_blocks_in_mbc = 0;
+ state->block_size = GET_TEST_MBC_SIZE() / (BLOCKS_PER_MBC+1);
+ if (MAX_BLOCK_PER_THR * state->block_size < tcs->free_mem) {
+ state->max_nblocks = MAX_BLOCK_PER_THR;
+ } else {
+ state->max_nblocks = tcs->free_mem / state->block_size;
+ }
+ state->goal_nblocks = rand_int(state, 1, state->max_nblocks);
+ }
+
+ switch (state->phase) {
+ case GROWING: {
+ MyBlock* p;
+ FATAL_ASSERT(!state->blockv[state->nblocks]);
+ p = ALLOC_TEST(rand_int(state, state->block_size/2, state->block_size));
+ FATAL_ASSERT(p);
+ add_block(p, state);
+ state->blockv[state->nblocks] = p;
+ if (++state->nblocks >= state->goal_nblocks) {
+ /*testcase_printf(tcs, "%d: Grown to %d blocks", tcs->thr_nr, state->nblocks);*/
+ state->phase = SHRINKING;
+ state->goal_nblocks = rand_int(state, 0, state->goal_nblocks-1);
+ }
+ else
+ FATAL_ASSERT(!state->blockv[state->nblocks]);
+ break;
+ }
+ case SHRINKING: {
+ int ix = rand_int(state, 0, state->nblocks-1);
+ FATAL_ASSERT(state->blockv[ix]);
+ remove_block(state->blockv[ix]);
+ FREE_TEST(state->blockv[ix]);
+ state->blockv[ix] = state->blockv[--state->nblocks];
+ state->blockv[state->nblocks] = NULL;
+
+ if (state->nblocks <= state->goal_nblocks) {
+ /*testcase_printf(tcs, "%d: Shrunk to %d blocks", tcs->thr_nr, state->nblocks);*/
+ if (++state->round >= MAX_ROUNDS) {
+ state->phase = CLEANUP;
+ } else {
+ state->phase = GROWING;
+ state->goal_nblocks = rand_int(state, state->goal_nblocks+1, state->max_nblocks);
+ }
+ }
+ break;
+ }
+ case CLEANUP:
+ do_cleanup(tcs, state);
+ break;
+
+ default:
+ FATAL_ASSERT(!"Invalid phase");
+ }
+
+ if (state->phase == DONE) {
+ }
+ else {
+ testcase_continue(tcs);
+ }
+}
+
+void
+testcase_cleanup(TestCaseState_t *tcs)
+{
+ MigrationState* state = (MigrationState*) tcs->extra;
+
+ while (state->phase != DONE)
+ do_cleanup(tcs, state);
+
+ enif_free(tcs->extra);
+ tcs->extra = NULL;
+}
+
+
+ERL_NIF_INIT(migration, testcase_nif_funcs, migration_init,
+ NULL, NULL, NULL);
diff --git a/erts/emulator/test/alloc_SUITE_data/migration.erl b/erts/emulator/test/alloc_SUITE_data/migration.erl
new file mode 100644
index 0000000000..440a99becd
--- /dev/null
+++ b/erts/emulator/test/alloc_SUITE_data/migration.erl
@@ -0,0 +1,10 @@
+-module(migration).
+
+-export([init/1, start/1, run/1, stop/1]).
+
+init(File) ->
+ ok = erlang:load_nif(File, 0).
+
+start(_) -> erlang:nif_error(not_loaded).
+run(_) -> erlang:nif_error(not_loaded).
+stop(_) -> erlang:nif_error(not_loaded).
diff --git a/erts/emulator/test/alloc_SUITE_data/mseg_clear_cache.c b/erts/emulator/test/alloc_SUITE_data/mseg_clear_cache.c
index 9c03f3a331..e5df3d647f 100644
--- a/erts/emulator/test/alloc_SUITE_data/mseg_clear_cache.c
+++ b/erts/emulator/test/alloc_SUITE_data/mseg_clear_cache.c
@@ -101,3 +101,6 @@ testcase_cleanup(TestCaseState_t *tcs)
tcs->extra = NULL;
}
}
+
+ERL_NIF_INIT(mseg_clear_cache, testcase_nif_funcs, testcase_nif_init,
+ NULL, NULL, NULL);
diff --git a/erts/emulator/test/alloc_SUITE_data/mseg_clear_cache.erl b/erts/emulator/test/alloc_SUITE_data/mseg_clear_cache.erl
new file mode 100644
index 0000000000..befd6c2e8e
--- /dev/null
+++ b/erts/emulator/test/alloc_SUITE_data/mseg_clear_cache.erl
@@ -0,0 +1,10 @@
+-module(mseg_clear_cache).
+
+-export([init/1, start/1, run/1, stop/1]).
+
+init(File) ->
+ ok = erlang:load_nif(File, 0).
+
+start(_) -> erlang:nif_error(not_loaded).
+run(_) -> erlang:nif_error(not_loaded).
+stop(_) -> erlang:nif_error(not_loaded).
diff --git a/erts/emulator/test/alloc_SUITE_data/rbtree.c b/erts/emulator/test/alloc_SUITE_data/rbtree.c
index 8d4d5535a8..38bbbdf90c 100644
--- a/erts/emulator/test/alloc_SUITE_data/rbtree.c
+++ b/erts/emulator/test/alloc_SUITE_data/rbtree.c
@@ -20,7 +20,7 @@
#include "testcase_driver.h"
#include "allocator_test.h"
-#define NO_BLOCKS 100000
+int NO_BLOCKS;
#define RIGHT_VISITED (1 << 0)
#define LEFT_VISITED (1 << 1)
@@ -265,9 +265,10 @@ check_tree(TestCaseState_t *tcs, Allctr_t *alc, Ulong size)
ASSERT(tcs, curr_blacks == 0);
ASSERT(tcs, i == -1);
+ /*
testcase_printf(tcs, "Red-Black Tree OK! Max depth = %d; "
"Black depth = %d\n", max_i+1, blacks < 0 ? 0 : blacks);
-
+ */
return res;
}
@@ -468,6 +469,12 @@ testcase_run(TestCaseState_t *tcs)
Allctr_t *a;
rbtree_test_data *td;
+ NO_BLOCKS = 100*1000;
+ if (enif_is_identical(tcs->build_type,
+ enif_make_atom(tcs->curr_env,"valgrind"))) {
+ NO_BLOCKS /= 10;
+ }
+
/* Best fit... */
testcase_printf(tcs, "Setup...\n");
@@ -577,3 +584,6 @@ testcase_run(TestCaseState_t *tcs)
testcase_printf(tcs, "aoffcaobf test succeeded!\n");
}
+
+ERL_NIF_INIT(rbtree, testcase_nif_funcs, testcase_nif_init,
+ NULL, NULL, NULL);
diff --git a/erts/emulator/test/alloc_SUITE_data/rbtree.erl b/erts/emulator/test/alloc_SUITE_data/rbtree.erl
new file mode 100644
index 0000000000..f5b7120ff2
--- /dev/null
+++ b/erts/emulator/test/alloc_SUITE_data/rbtree.erl
@@ -0,0 +1,10 @@
+-module(rbtree).
+
+-export([init/1, start/1, run/1, stop/1]).
+
+init(File) ->
+ ok = erlang:load_nif(File, 0).
+
+start(_) -> erlang:nif_error(not_loaded).
+run(_) -> erlang:nif_error(not_loaded).
+stop(_) -> erlang:nif_error(not_loaded).
diff --git a/erts/emulator/test/alloc_SUITE_data/realloc_copy.c b/erts/emulator/test/alloc_SUITE_data/realloc_copy.c
index e405f06225..c4147eb00d 100644
--- a/erts/emulator/test/alloc_SUITE_data/realloc_copy.c
+++ b/erts/emulator/test/alloc_SUITE_data/realloc_copy.c
@@ -278,3 +278,5 @@ testcase_cleanup(TestCaseState_t *tcs)
STOP_ALC((Allctr_t *) tcs->extra);
}
+ERL_NIF_INIT(realloc_copy, testcase_nif_funcs, testcase_nif_init,
+ NULL, NULL, NULL);
diff --git a/erts/emulator/test/alloc_SUITE_data/realloc_copy.erl b/erts/emulator/test/alloc_SUITE_data/realloc_copy.erl
new file mode 100644
index 0000000000..cc6617bf64
--- /dev/null
+++ b/erts/emulator/test/alloc_SUITE_data/realloc_copy.erl
@@ -0,0 +1,10 @@
+-module(realloc_copy).
+
+-export([init/1, start/1, run/1, stop/1]).
+
+init(File) ->
+ ok = erlang:load_nif(File, 0).
+
+start(_) -> erlang:nif_error(not_loaded).
+run(_) -> erlang:nif_error(not_loaded).
+stop(_) -> erlang:nif_error(not_loaded).
diff --git a/erts/emulator/test/alloc_SUITE_data/testcase_driver.c b/erts/emulator/test/alloc_SUITE_data/testcase_driver.c
index bc674c56b7..7dcca544e5 100644
--- a/erts/emulator/test/alloc_SUITE_data/testcase_driver.c
+++ b/erts/emulator/test/alloc_SUITE_data/testcase_driver.c
@@ -23,141 +23,147 @@
#include <stdarg.h>
#include <setjmp.h>
#include <string.h>
+#include <limits.h>
#ifdef __WIN32__
-#undef HAVE_VSNPRINTF
-#define HAVE_VSNPRINTF 1
-#define vsnprintf _vsnprintf
+static void my_vsnprintf(char *outBuf, size_t size, const char *format, va_list ap)
+{
+ _vsnprintf(outBuf, size, format, ap);
+ outBuf[size-1] = 0; /* be sure string is terminated */
+}
+#elif defined(HAVE_VSNPRINTF)
+# define my_vsnprintf(B,S,F,A) (void)vsnprintf(B,S,F,A)
+#else
+# warning Using unsafe 'vsprintf' without buffer overflow protection
+# define my_vsnprintf(B,S,F,A) (void)vsprintf(B,F,A)
#endif
-#ifndef HAVE_VSNPRINTF
-#define HAVE_VSNPRINTF 0
-#endif
+static void my_snprintf(char *outBuf, size_t size, const char *format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ my_vsnprintf(outBuf, size, format, ap);
+ va_end(ap);
+}
#define COMMENT_BUF_SZ 4096
#define TESTCASE_FAILED 0
#define TESTCASE_SKIPPED 1
#define TESTCASE_SUCCEEDED 2
+#define TESTCASE_CONTINUE 3
typedef struct {
TestCaseState_t visible;
- ErlDrvPort port;
- ErlDrvTermData port_id;
int result;
- jmp_buf done_jmp_buf;
+ jmp_buf* done_jmp_buf;
char *comment;
char comment_buf[COMMENT_BUF_SZ];
} InternalTestCaseState_t;
-ErlDrvData testcase_drv_start(ErlDrvPort port, char *command);
-void testcase_drv_stop(ErlDrvData drv_data);
-void testcase_drv_run(ErlDrvData drv_data, char *buf, ErlDrvSizeT len);
-
-static ErlDrvEntry testcase_drv_entry = {
- NULL,
- testcase_drv_start,
- testcase_drv_stop,
- testcase_drv_run,
- NULL,
- NULL,
- "testcase_drv",
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- ERL_DRV_EXTENDED_MARKER,
- ERL_DRV_EXTENDED_MAJOR_VERSION,
- ERL_DRV_EXTENDED_MINOR_VERSION,
- 0,
- NULL,
- NULL,
- NULL
+ERL_NIF_TERM testcase_nif_start(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+ERL_NIF_TERM testcase_nif_stop(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+ERL_NIF_TERM testcase_nif_run(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+
+ErlNifFunc testcase_nif_funcs[] =
+{
+ {"start", 1, testcase_nif_start},
+ {"run", 1, testcase_nif_run},
+ {"stop", 1, testcase_nif_stop}
};
+static ErlNifResourceType* testcase_rt;
+static ERL_NIF_TERM print_atom;
-DRIVER_INIT(testcase_drv)
+int testcase_nif_init(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
{
- testcase_drv_entry.driver_name = testcase_name();
- return &testcase_drv_entry;
+ testcase_rt = enif_open_resource_type(env, NULL, "testcase_rt", NULL,
+ ERL_NIF_RT_CREATE, NULL);
+
+ print_atom = enif_make_atom(env, "print");
+ return 0;
}
-ErlDrvData
-testcase_drv_start(ErlDrvPort port, char *command)
-{
+ERL_NIF_TERM
+testcase_nif_start(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{ /* (ThrNr, FreeMeg, BuildType) */
+ ERL_NIF_TERM ret;
InternalTestCaseState_t *itcs = (InternalTestCaseState_t *)
- driver_alloc(sizeof(InternalTestCaseState_t));
- if (!itcs) {
- return ERL_DRV_ERROR_GENERAL;
+ enif_alloc_resource(testcase_rt, sizeof(InternalTestCaseState_t));
+ int free_megabyte;
+ const int max_megabyte = INT_MAX / (1024*1024);
+ const ERL_NIF_TERM* tpl;
+ int tpl_arity;
+
+ if (!itcs
+ || !enif_get_tuple(env, argv[0], &tpl_arity, &tpl)
+ || tpl_arity != 3
+ || !enif_get_int(env, tpl[0], &itcs->visible.thr_nr)
+ || !enif_get_int(env, tpl[1], &free_megabyte)) {
+ enif_make_badarg(env);
}
-
+ itcs->visible.free_mem = (free_megabyte < max_megabyte ?
+ free_megabyte : max_megabyte) * (1024*1024);
itcs->visible.testcase_name = testcase_name();
+ itcs->visible.build_type = tpl[2];
itcs->visible.extra = NULL;
- itcs->port = port;
- itcs->port_id = driver_mk_port(port);
itcs->result = TESTCASE_FAILED;
itcs->comment = "";
- return (ErlDrvData) itcs;
+ ret = enif_make_resource(env, itcs);
+ enif_release_resource(itcs);
+ return ret;
}
-void
-testcase_drv_stop(ErlDrvData drv_data)
+ERL_NIF_TERM
+testcase_nif_stop(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
- testcase_cleanup((TestCaseState_t *) drv_data);
- driver_free((void *) drv_data);
+ InternalTestCaseState_t *itcs;
+ if (!enif_get_resource(env, argv[0], testcase_rt, (void**)&itcs))
+ return enif_make_badarg(env);
+ testcase_cleanup(&itcs->visible);
+ return enif_make_atom(env,"ok");
}
-void
-testcase_drv_run(ErlDrvData drv_data, char *buf, ErlDrvSizeT len)
+ERL_NIF_TERM
+testcase_nif_run(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
- InternalTestCaseState_t *itcs = (InternalTestCaseState_t *) drv_data;
- ErlDrvTermData result_atom;
- ErlDrvTermData msg[12];
+ InternalTestCaseState_t *itcs;
+ const char* result_atom;
+ jmp_buf the_jmp_buf;
+
+ if (!enif_get_resource(env, argv[0], testcase_rt, (void**)&itcs))
+ return enif_make_badarg(env);
- itcs->visible.command = buf;
- itcs->visible.command_len = len;
+ itcs->visible.curr_env = env;
- if (setjmp(itcs->done_jmp_buf) == 0) {
- testcase_run((TestCaseState_t *) itcs);
+ /* For some unknown reason, first call to setjmp crashes on win64
+ * when jmp_buf is allocated as part of the resource. But it works when
+ * allocated on stack. It used to work when this was a driver.
+ */
+ itcs->done_jmp_buf = &the_jmp_buf;
+
+ if (setjmp(the_jmp_buf) == 0) {
+ testcase_run(&itcs->visible);
itcs->result = TESTCASE_SUCCEEDED;
}
switch (itcs->result) {
- case TESTCASE_SUCCEEDED:
- result_atom = driver_mk_atom("succeeded");
- break;
- case TESTCASE_SKIPPED:
- result_atom = driver_mk_atom("skipped");
- break;
- case TESTCASE_FAILED:
+ case TESTCASE_CONTINUE:
+ return enif_make_atom(env, "continue");
+
+ case TESTCASE_SUCCEEDED: result_atom = "succeeded"; break;
+ case TESTCASE_SKIPPED: result_atom = "skipped"; break;
+ case TESTCASE_FAILED: result_atom = "failed"; break;
default:
- result_atom = driver_mk_atom("failed");
- break;
+ result_atom = "failed";
+ my_snprintf(itcs->comment_buf, sizeof(itcs->comment_buf),
+ "Unexpected test result code %d.", itcs->result);
+ itcs->comment = itcs->comment_buf;
}
- msg[0] = ERL_DRV_ATOM;
- msg[1] = (ErlDrvTermData) result_atom;
-
- msg[2] = ERL_DRV_PORT;
- msg[3] = itcs->port_id;
-
- msg[4] = ERL_DRV_ATOM;
- msg[5] = driver_mk_atom(itcs->visible.testcase_name);
-
- msg[6] = ERL_DRV_STRING;
- msg[7] = (ErlDrvTermData) itcs->comment;
- msg[8] = (ErlDrvTermData) strlen(itcs->comment);
-
- msg[9] = ERL_DRV_TUPLE;
- msg[10] = (ErlDrvTermData) 4;
-
- erl_drv_output_term(itcs->port_id, msg, 11);
+ return enif_make_tuple2(env, enif_make_atom(env, result_atom),
+ enif_make_string(env, itcs->comment, ERL_NIF_LATIN1));
}
int
@@ -172,34 +178,22 @@ testcase_assertion_failed(TestCaseState_t *tcs,
void
testcase_printf(TestCaseState_t *tcs, char *frmt, ...)
{
- InternalTestCaseState_t *itcs = (InternalTestCaseState_t *) tcs;
- ErlDrvTermData msg[12];
+ InternalTestCaseState_t* itcs = (InternalTestCaseState_t*)tcs;
+ ErlNifPid pid;
+ ErlNifEnv* msg_env = enif_alloc_env();
+ ERL_NIF_TERM msg;
va_list va;
va_start(va, frmt);
-#if HAVE_VSNPRINTF
- vsnprintf(itcs->comment_buf, COMMENT_BUF_SZ, frmt, va);
-#else
- vsprintf(itcs->comment_buf, frmt, va);
-#endif
+ my_vsnprintf(itcs->comment_buf, COMMENT_BUF_SZ, frmt, va);
va_end(va);
- msg[0] = ERL_DRV_ATOM;
- msg[1] = (ErlDrvTermData) driver_mk_atom("print");
+ msg = enif_make_tuple2(msg_env, print_atom,
+ enif_make_string(msg_env, itcs->comment_buf, ERL_NIF_LATIN1));
- msg[2] = ERL_DRV_PORT;
- msg[3] = itcs->port_id;
+ enif_send(itcs->visible.curr_env, enif_self(itcs->visible.curr_env, &pid),
+ msg_env, msg);
- msg[4] = ERL_DRV_ATOM;
- msg[5] = driver_mk_atom(itcs->visible.testcase_name);
-
- msg[6] = ERL_DRV_STRING;
- msg[7] = (ErlDrvTermData) itcs->comment_buf;
- msg[8] = (ErlDrvTermData) strlen(itcs->comment_buf);
-
- msg[9] = ERL_DRV_TUPLE;
- msg[10] = (ErlDrvTermData) 4;
-
- erl_drv_output_term(itcs->port_id, msg, 11);
+ enif_free_env(msg_env);
}
@@ -208,17 +202,13 @@ void testcase_succeeded(TestCaseState_t *tcs, char *frmt, ...)
InternalTestCaseState_t *itcs = (InternalTestCaseState_t *) tcs;
va_list va;
va_start(va, frmt);
-#if HAVE_VSNPRINTF
- vsnprintf(itcs->comment_buf, COMMENT_BUF_SZ, frmt, va);
-#else
- vsprintf(itcs->comment_buf, frmt, va);
-#endif
+ my_vsnprintf(itcs->comment_buf, COMMENT_BUF_SZ, frmt, va);
va_end(va);
itcs->result = TESTCASE_SUCCEEDED;
itcs->comment = itcs->comment_buf;
- longjmp(itcs->done_jmp_buf, 1);
+ longjmp(*itcs->done_jmp_buf, 1);
}
void testcase_skipped(TestCaseState_t *tcs, char *frmt, ...)
@@ -226,17 +216,20 @@ void testcase_skipped(TestCaseState_t *tcs, char *frmt, ...)
InternalTestCaseState_t *itcs = (InternalTestCaseState_t *) tcs;
va_list va;
va_start(va, frmt);
-#if HAVE_VSNPRINTF
- vsnprintf(itcs->comment_buf, COMMENT_BUF_SZ, frmt, va);
-#else
- vsprintf(itcs->comment_buf, frmt, va);
-#endif
+ my_vsnprintf(itcs->comment_buf, COMMENT_BUF_SZ, frmt, va);
va_end(va);
itcs->result = TESTCASE_SKIPPED;
itcs->comment = itcs->comment_buf;
- longjmp(itcs->done_jmp_buf, 1);
+ longjmp(*itcs->done_jmp_buf, 1);
+}
+
+void testcase_continue(TestCaseState_t *tcs)
+{
+ InternalTestCaseState_t *itcs = (InternalTestCaseState_t *) tcs;
+ itcs->result = TESTCASE_CONTINUE;
+ longjmp(*itcs->done_jmp_buf, 1);
}
void testcase_failed(TestCaseState_t *tcs, char *frmt, ...)
@@ -246,37 +239,33 @@ void testcase_failed(TestCaseState_t *tcs, char *frmt, ...)
size_t bufsz = sizeof(buf);
va_list va;
va_start(va, frmt);
-#if HAVE_VSNPRINTF
- vsnprintf(itcs->comment_buf, COMMENT_BUF_SZ, frmt, va);
-#else
- vsprintf(itcs->comment_buf, frmt, va);
-#endif
+ my_vsnprintf(itcs->comment_buf, COMMENT_BUF_SZ, frmt, va);
va_end(va);
itcs->result = TESTCASE_FAILED;
itcs->comment = itcs->comment_buf;
- if (erl_drv_getenv("ERL_ABORT_ON_FAILURE", buf, &bufsz) == 0
+ if (enif_getenv("ERL_ABORT_ON_FAILURE", buf, &bufsz) == 0
&& strcmp("true", buf) == 0) {
fprintf(stderr, "Testcase \"%s\" failed: %s\n",
itcs->visible.testcase_name, itcs->comment);
abort();
}
- longjmp(itcs->done_jmp_buf, 1);
+ longjmp(*itcs->done_jmp_buf, 1);
}
void *testcase_alloc(size_t size)
{
- return driver_alloc(size);
+ return enif_alloc(size);
}
void *testcase_realloc(void *ptr, size_t size)
{
- return driver_realloc(ptr, size);
+ return enif_realloc(ptr, size);
}
void testcase_free(void *ptr)
{
- driver_free(ptr);
+ enif_free(ptr);
}
diff --git a/erts/emulator/test/alloc_SUITE_data/testcase_driver.h b/erts/emulator/test/alloc_SUITE_data/testcase_driver.h
index 5d17eaec64..f0ca91bd06 100644
--- a/erts/emulator/test/alloc_SUITE_data/testcase_driver.h
+++ b/erts/emulator/test/alloc_SUITE_data/testcase_driver.h
@@ -20,13 +20,15 @@
#ifndef TESTCASE_DRIVER_H__
#define TESTCASE_DRIVER_H__
-#include "erl_driver.h"
+#include "erl_nif.h"
#include <stdlib.h>
typedef struct {
+ ErlNifEnv* curr_env;
char *testcase_name;
- char *command;
- int command_len;
+ int thr_nr;
+ int free_mem; /* in bytes */
+ ERL_NIF_TERM build_type; /* opt, debug, valgrind, ... */
void *extra;
} TestCaseState_t;
@@ -34,9 +36,11 @@ typedef struct {
((void) ((B) ? 1 : testcase_assertion_failed((TCS), __FILE__, __LINE__, #B)))
+int testcase_nif_init(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info);
void testcase_printf(TestCaseState_t *tcs, char *frmt, ...);
void testcase_succeeded(TestCaseState_t *tcs, char *frmt, ...);
void testcase_skipped(TestCaseState_t *tcs, char *frmt, ...);
+void testcase_continue(TestCaseState_t *tcs);
void testcase_failed(TestCaseState_t *tcs, char *frmt, ...);
int testcase_assertion_failed(TestCaseState_t *tcs, char *file, int line,
char *assertion);
@@ -45,8 +49,11 @@ void *testcase_realloc(void *ptr, size_t size);
void testcase_free(void *ptr);
+/* Implemented by testcase: */
char *testcase_name(void);
void testcase_run(TestCaseState_t *tcs);
void testcase_cleanup(TestCaseState_t *tcs);
-#endif
+extern ErlNifFunc testcase_nif_funcs[3];
+
+#endif /* TESTCASE_DRIVER_H__ */
diff --git a/erts/emulator/test/alloc_SUITE_data/threads.c b/erts/emulator/test/alloc_SUITE_data/threads.c
index edad24ee6b..a8a6a23695 100644
--- a/erts/emulator/test/alloc_SUITE_data/threads.c
+++ b/erts/emulator/test/alloc_SUITE_data/threads.c
@@ -86,7 +86,7 @@ static void fail(int t_no, char *frmt, ...)
tc_failed = 1;
- if (erl_drv_getenv("ERL_ABORT_ON_FAILURE", buf, &bufsz) == 0
+ if (enif_getenv("ERL_ABORT_ON_FAILURE", buf, &bufsz) == 0
&& strcmp("true", buf) == 0) {
fprintf(stderr, "Testcase \"%s\" failed: %s\n",
testcase_name(), err_buf);
@@ -187,7 +187,6 @@ testcase_run(TestCaseState_t *tcs)
for(i = 1; i <= NO_OF_THREADS; i++) {
char *alc;
- int res;
threads[i].arg.no_ops_per_bl = NO_OF_OPS_PER_BL;
@@ -446,3 +445,6 @@ thread_func(void *arg)
exit_thread(td->t_no, 1);
return NULL;
}
+
+ERL_NIF_INIT(threads, testcase_nif_funcs, testcase_nif_init,
+ NULL, NULL, NULL);
diff --git a/erts/emulator/test/alloc_SUITE_data/threads.erl b/erts/emulator/test/alloc_SUITE_data/threads.erl
new file mode 100644
index 0000000000..a7b4965f5e
--- /dev/null
+++ b/erts/emulator/test/alloc_SUITE_data/threads.erl
@@ -0,0 +1,10 @@
+-module(threads).
+
+-export([init/1, start/1, run/1, stop/1]).
+
+init(File) ->
+ ok = erlang:load_nif(File, 0).
+
+start(_) -> erlang:nif_error(not_loaded).
+run(_) -> erlang:nif_error(not_loaded).
+stop(_) -> erlang:nif_error(not_loaded).
diff --git a/erts/emulator/test/binary_SUITE.erl b/erts/emulator/test/binary_SUITE.erl
index 96ba2f64d4..f8f71efecc 100644
--- a/erts/emulator/test/binary_SUITE.erl
+++ b/erts/emulator/test/binary_SUITE.erl
@@ -521,30 +521,29 @@ external_size_1(Term, Size0, Limit) when Size0 < Limit ->
external_size_1(_, _, _) -> ok.
t_iolist_size(Config) when is_list(Config) ->
- ?line Seed = {erlang:monotonic_time(),
- erlang:time_offset(),
- erlang:unique_integer([positive])},
- ?line io:format("Seed: ~p", [Seed]),
- ?line random:seed(Seed),
- ?line Base = <<0:(1 bsl 20)/unit:8>>,
- ?line Powers = [1 bsl N || N <- lists:seq(2, 37)],
- ?line Sizes0 = [[N - random:uniform(N div 2),
- lists:seq(N-2, N+2),
- N+N div 2,
- N + random:uniform(N div 2)] ||
- N <- Powers],
+ _ = rand:uniform(), %Seed generator
+ io:format("Seed: ~p", [rand:export_seed()]),
+
+ Base = <<0:(1 bsl 20)/unit:8>>,
+ Powers = [1 bsl N || N <- lists:seq(2, 37)],
+ Sizes0 = [[N - rand:uniform(N div 2),
+ lists:seq(N-2, N+2),
+ N+N div 2,
+ N + rand:uniform(N div 2)] ||
+ N <- Powers],
+
%% Test sizes around 1^32 more thoroughly.
FourGigs = 1 bsl 32,
- ?line Sizes1 = [FourGigs+N || N <- lists:seq(-8, 40)] ++ Sizes0,
- ?line Sizes2 = lists:flatten(Sizes1),
- ?line Sizes = lists:usort(Sizes2),
+ Sizes1 = [FourGigs+N || N <- lists:seq(-8, 40)] ++ Sizes0,
+ Sizes2 = lists:flatten(Sizes1),
+ Sizes = lists:usort(Sizes2),
io:format("~p sizes:", [length(Sizes)]),
io:format("~p\n", [Sizes]),
- ?line [Sz = iolist_size(build_iolist(Sz, Base)) || Sz <- Sizes],
+ _ = [Sz = iolist_size(build_iolist(Sz, Base)) || Sz <- Sizes],
ok.
build_iolist(N, Base) when N < 16 ->
- case random:uniform(3) of
+ case rand:uniform(3) of
1 ->
<<Bin:N/binary,_/binary>> = Base,
Bin;
@@ -552,7 +551,7 @@ build_iolist(N, Base) when N < 16 ->
lists:seq(1, N)
end;
build_iolist(N, Base) when N =< byte_size(Base) ->
- case random:uniform(3) of
+ case rand:uniform(3) of
1 ->
<<Bin:N/binary,_/binary>> = Base,
Bin;
@@ -570,7 +569,7 @@ build_iolist(N, Base) when N =< byte_size(Base) ->
end
end;
build_iolist(N0, Base) ->
- Small = random:uniform(15),
+ Small = rand:uniform(15),
Seq = lists:seq(1, Small),
N = N0 - Small,
case N rem 2 of
@@ -1604,7 +1603,7 @@ bit_sized_binary(Bin0) ->
unaligned_sub_bin(Bin, 0) -> Bin;
unaligned_sub_bin(Bin0, Offs) ->
- F = random:uniform(256),
+ F = rand:uniform(256),
Roffs = 8-Offs,
Bin1 = <<F:Offs,Bin0/binary,F:Roffs>>,
Sz = size(Bin0),
diff --git a/erts/emulator/test/bs_bincomp_SUITE.erl b/erts/emulator/test/bs_bincomp_SUITE.erl
index dcd13c19df..8836fe40ae 100644
--- a/erts/emulator/test/bs_bincomp_SUITE.erl
+++ b/erts/emulator/test/bs_bincomp_SUITE.erl
@@ -131,7 +131,7 @@ tracing(Config) when is_list(Config) ->
random_binary() ->
Seq = [1,2,3,4,5,6,7,8,9,10],
- << <<($a + random:uniform($z - $a)):8>> || _ <- Seq >>.
+ << <<($a + rand:uniform($z - $a)):8>> || _ <- Seq >>.
random_binaries(N) when N > 0 ->
random_binary(),
diff --git a/erts/emulator/test/code_SUITE.erl b/erts/emulator/test/code_SUITE.erl
index 9f318a38be..1acc4538fb 100644
--- a/erts/emulator/test/code_SUITE.erl
+++ b/erts/emulator/test/code_SUITE.erl
@@ -26,7 +26,8 @@
t_check_process_code_ets/1,
external_fun/1,get_chunk/1,module_md5/1,make_stub/1,
make_stub_many_funs/1,constant_pools/1,constant_refc_binaries/1,
- false_dependency/1,coverage/1,fun_confusion/1]).
+ false_dependency/1,coverage/1,fun_confusion/1,
+ t_copy_literals/1]).
-define(line_trace, 1).
-include_lib("test_server/include/test_server.hrl").
@@ -38,7 +39,7 @@ all() ->
t_check_process_code_ets, t_check_old_code, external_fun, get_chunk,
module_md5, make_stub, make_stub_many_funs,
constant_pools, constant_refc_binaries, false_dependency,
- coverage, fun_confusion].
+ coverage, fun_confusion, t_copy_literals].
groups() ->
[].
@@ -753,6 +754,80 @@ compile_load(Mod, Src, Ver) ->
{module,Mod} = code:load_binary(Mod, "fun_confusion.beam", Code1),
ok.
+
+t_copy_literals(Config) when is_list(Config) ->
+ %% Compile the the literals module.
+ Data = ?config(data_dir, Config),
+ File = filename:join(Data, "literals"),
+ {ok,literals,Code} = compile:file(File, [report,binary]),
+ {module,literals} = erlang:load_module(literals, Code),
+
+ N = 30,
+ Me = self(),
+ %% reload literals code every 567 ms
+ Rel = spawn_link(fun() -> reloader(literals,Code,567) end),
+ %% add new literal msgs to the loop every 789 ms
+ Sat = spawn_link(fun() -> saturate(Me,789) end),
+ %% run for 10s
+ _ = spawn_link(fun() -> receive after 10000 -> Me ! done end end),
+ ok = chase_msg(N, Me),
+ %% cleanup
+ Rel ! done,
+ Sat ! done,
+ ok = flush(),
+ ok.
+
+
+chase_msg(0, Pid) ->
+ chase_loop(Pid);
+chase_msg(N, Master) ->
+ Pid = spawn_link(fun() -> chase_msg(N - 1,Master) end),
+ chase_loop(Pid).
+
+chase_loop(Pid) ->
+ receive
+ done ->
+ Pid ! done,
+ ok;
+ {_From,Msg} ->
+ Pid ! {self(), Msg},
+ ok = traverse(Msg),
+ chase_loop(Pid)
+ end.
+
+saturate(Pid,Time) ->
+ Es = [msg1,msg2,msg3,msg4,msg5],
+ Msg = [literals:E()||E <- Es],
+ Pid ! {self(), Msg},
+ receive
+ done -> ok
+ after Time ->
+ saturate(Pid,Time)
+ end.
+
+traverse([]) -> ok;
+traverse([H|T]) ->
+ ok = traverse(H),
+ traverse(T);
+traverse(T) when is_tuple(T) -> ok;
+traverse(B) when is_binary(B) -> ok;
+traverse(I) when is_integer(I) -> ok;
+traverse(#{ 1 := V1, b := V2 }) ->
+ ok = traverse(V1),
+ ok = traverse(V2),
+ ok.
+
+
+reloader(Mod,Code,Time) ->
+ receive
+ done -> ok
+ after Time ->
+ code:purge(Mod),
+ {module,Mod} = erlang:load_module(Mod, Code),
+ reloader(Mod,Code,Time)
+ end.
+
+
%% Utilities.
make_sub_binary(Bin) when is_binary(Bin) ->
@@ -775,4 +850,7 @@ bit_sized_binary(Bin0) ->
BitSize = 8*size(Bin) + 1,
Bin.
+flush() ->
+ receive _ -> flush() after 0 -> ok end.
+
id(I) -> I.
diff --git a/erts/emulator/test/code_SUITE_data/literals.erl b/erts/emulator/test/code_SUITE_data/literals.erl
index 9802d9d3f9..a36bfe09dd 100644
--- a/erts/emulator/test/code_SUITE_data/literals.erl
+++ b/erts/emulator/test/code_SUITE_data/literals.erl
@@ -20,6 +20,7 @@
-module(literals).
-export([a/0,b/0,huge_bignum/0,binary/0,unused_binaries/0,bits/0]).
+-export([msg1/0,msg2/0,msg3/0,msg4/0,msg5/0]).
a() ->
{a,42.0,[7,38877938333399637266518333334747]}.
@@ -101,3 +102,9 @@ unused_binaries() ->
bits() ->
{bits,<<42:13,?MB_1>>}.
+
+msg1() -> "halloj".
+msg2() -> {"hello","world"}.
+msg3() -> <<"halloj">>.
+msg4() -> #{ 1=> "hello", b => "world"}.
+msg5() -> {1,2,3,4,5,6}.
diff --git a/erts/emulator/test/decode_packet_SUITE.erl b/erts/emulator/test/decode_packet_SUITE.erl
index 6a5ca20ac3..65ae94d0dc 100644
--- a/erts/emulator/test/decode_packet_SUITE.erl
+++ b/erts/emulator/test/decode_packet_SUITE.erl
@@ -53,11 +53,8 @@ end_per_group(_GroupName, Config) ->
init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
- Seed = {S1,S2,S3} = {erlang:monotonic_time(),
- erlang:time_offset(),
- erlang:unique_integer()},
- random:seed(S1,S2,S3),
- io:format("*** SEED: ~p ***\n", [Seed]),
+ rand:seed(exsplus),
+ io:format("*** SEED: ~p ***\n", [rand:export_seed()]),
Dog=?t:timetrap(?t:minutes(1)),
[{watchdog, Dog}|Config].
@@ -136,7 +133,7 @@ pack(Type,Body,Rest,BitOffs) ->
{Packet,Unpacked} = pack(Type,Body),
%% Make Bin a sub-bin with an arbitrary bitoffset within Orig
- Prefix = random:uniform(1 bsl BitOffs) - 1,
+ Prefix = rand:uniform(1 bsl BitOffs) - 1,
Orig = <<Prefix:BitOffs,Packet/binary,Rest/bits>>,
<<_:BitOffs,Bin/bits>> = Orig,
{Bin,Unpacked,Orig}.
@@ -151,13 +148,13 @@ pack(4,Bin) ->
Psz = byte_size(Bin),
{<<Psz:32,Bin/binary>>, Bin};
pack(asn1,Bin) ->
- Ident = case random:uniform(3) of
+ Ident = case rand:uniform(3) of
1 -> <<17>>;
2 -> <<16#1f,16#81,17>>;
3 -> <<16#1f,16#81,16#80,16#80,17>>
end,
Psz = byte_size(Bin),
- Length = case random:uniform(4) of
+ Length = case rand:uniform(4) of
1 when Psz < 128 ->
<<Psz:8>>;
R when R=<2 andalso Psz < 16#10000 ->
@@ -177,42 +174,42 @@ pack(sunrm,Bin) ->
{Res,Res};
pack(cdr,Bin) ->
GIOP = <<"GIOP">>,
- Major = random:uniform(256) - 1,
- Minor = random:uniform(256) - 1,
- MType = random:uniform(256) - 1,
+ Major = rand:uniform(256) - 1,
+ Minor = rand:uniform(256) - 1,
+ MType = rand:uniform(256) - 1,
Psz = byte_size(Bin),
- Res = case random:uniform(2) of
+ Res = case rand:uniform(2) of
1 -> <<GIOP/binary,Major:8,Minor:8,0:8,MType:8,Psz:32/big,Bin/binary>>;
2 -> <<GIOP/binary,Major:8,Minor:8,1:8,MType:8,Psz:32/little,Bin/binary>>
end,
{Res,Res};
pack(fcgi,Bin) ->
Ver = 1,
- Type = random:uniform(256) - 1,
- Id = random:uniform(65536) - 1,
- PaddSz = random:uniform(16) - 1,
+ Type = rand:uniform(256) - 1,
+ Id = rand:uniform(65536) - 1,
+ PaddSz = rand:uniform(16) - 1,
Psz = byte_size(Bin),
- Reserv = random:uniform(256) - 1,
+ Reserv = rand:uniform(256) - 1,
Padd = case PaddSz of
0 -> <<>>;
- _ -> list_to_binary([random:uniform(256)-1
+ _ -> list_to_binary([rand:uniform(256)-1
|| _<- lists:seq(1,PaddSz)])
end,
Res = <<Ver:8,Type:8,Id:16,Psz:16/big,PaddSz:8,Reserv:8,Bin/binary>>,
{<<Res/binary,Padd/binary>>, Res};
pack(tpkt,Bin) ->
Ver = 3,
- Reserv = random:uniform(256) - 1,
+ Reserv = rand:uniform(256) - 1,
Size = byte_size(Bin) + 4,
Res = <<Ver:8,Reserv:8,Size:16,Bin/binary>>,
{Res, Res};
pack(ssl_tls,Bin) ->
- Content = case (random:uniform(256) - 1) of
+ Content = case (rand:uniform(256) - 1) of
C when C<128 -> C;
_ -> v2hello
end,
- Major = random:uniform(256) - 1,
- Minor = random:uniform(256) - 1,
+ Major = rand:uniform(256) - 1,
+ Minor = rand:uniform(256) - 1,
pack_ssl(Content,Major,Minor,Bin).
pack_ssl(Content, Major, Minor, Body) ->
@@ -371,10 +368,10 @@ http_do({Bin,[{_Line,PL,PB}|Tail]}, Type) ->
?line {ok, PB, Rest} = decode_pkt(http_with_bin(Type),Bin),
%% Same tests again but as SubBin
- PreLen = random:uniform(64),
- Prefix = random:uniform(1 bsl PreLen) - 1,
- SufLen = random:uniform(64),
- Suffix = random:uniform(1 bsl SufLen) - 1,
+ PreLen = rand:uniform(64),
+ Prefix = rand:uniform(1 bsl PreLen) - 1,
+ SufLen = rand:uniform(64),
+ Suffix = rand:uniform(1 bsl SufLen) - 1,
Orig = <<Prefix:PreLen, Bin/bits, Suffix:SufLen>>,
BinLen = bit_size(Bin),
<<_:PreLen, SubBin:BinLen/bits, _/bits>> = Orig, % Make SubBin
diff --git a/erts/emulator/test/distribution_SUITE_data/run.erl b/erts/emulator/test/distribution_SUITE_data/run.erl
index f5169e160c..d5ed139369 100644
--- a/erts/emulator/test/distribution_SUITE_data/run.erl
+++ b/erts/emulator/test/distribution_SUITE_data/run.erl
@@ -30,16 +30,19 @@ from(H, [_ | T]) -> from(H, T);
from(H, []) -> [].
start() ->
- net_kernel:start([fideridum,shortnames]),
- {ok, Node} = slave:start(host(), heppel),
- P = spawn(Node, a, b, []),
- B1 = term_to_binary(P),
- N1 = node(P),
- ok = net_kernel:stop(),
- N2 = node(P),
- io:format("~w~n", [N1 == N2]),
+ Result = do_it(),
+
+ %% Do GCs and node_and_dist_references
+ %% in an attempt to crash the VM (without OTP-13076 fix)
+ lists:foreach(fun(P) -> erlang:garbage_collect(P) end,
+ processes()),
+ erts_debug:set_internal_state(available_internal_state, true),
+ erts_debug:get_internal_state(node_and_dist_references),
+
+ io:format("~w~n", [Result]),
+
if
- N1 == N2 ->
+ Result ->
init:stop();
true ->
%% Make sure that the io:format/2 output is really written
@@ -47,3 +50,29 @@ start() ->
erlang:yield(),
init:stop()
end.
+
+
+do_it() ->
+ {ok, _} = net_kernel:start([fideridum,shortnames]),
+ {ok, Node} = slave:start(host(), heppel),
+ P = spawn(Node, net_kernel, stop, []),
+ B1 = term_to_binary(P),
+ N1 = node(P),
+ ok = net_kernel:stop(),
+ N2 = node(P),
+
+ %% OTP-13076
+ %% Restart distribution with same node name as previous remote node
+ %% Repeat to wrap around creation
+ Result = lists:foldl(fun(_, Acc) ->
+ timer:sleep(2), % give net_kernel:stop() time to take effect :-(
+ {ok, _} = net_kernel:start([heppel,shortnames]),
+ N3 = node(P),
+ ok = net_kernel:stop(),
+ N4 = node(P),
+ Acc and (N3 =:= N1) and (N4 =:= N1)
+ end,
+ (N2 =:= N1),
+ lists:seq(1,3)),
+
+ Result.
diff --git a/erts/emulator/test/driver_SUITE.erl b/erts/emulator/test/driver_SUITE.erl
index e17d0ff96c..ce55fe3c52 100644
--- a/erts/emulator/test/driver_SUITE.erl
+++ b/erts/emulator/test/driver_SUITE.erl
@@ -224,7 +224,7 @@ outputv_errors_1(Term) ->
port_close(Port).
build_iolist(N, Base) when N < 16 ->
- case random:uniform(3) of
+ case rand:uniform(3) of
1 ->
<<Bin:N/binary,_/binary>> = Base,
Bin;
@@ -232,7 +232,7 @@ build_iolist(N, Base) when N < 16 ->
lists:seq(1, N)
end;
build_iolist(N, Base) when N =< byte_size(Base) ->
- case random:uniform(3) of
+ case rand:uniform(3) of
1 ->
<<Bin:N/binary,_/binary>> = Base,
Bin;
@@ -250,7 +250,7 @@ build_iolist(N, Base) when N =< byte_size(Base) ->
end
end;
build_iolist(N0, Base) ->
- Small = random:uniform(15),
+ Small = rand:uniform(15),
Seq = lists:seq(1, Small),
N = N0 - Small,
case N rem 2 of
@@ -2524,14 +2524,7 @@ random_char() ->
uniform(256) - 1.
uniform(N) ->
- case get(random_seed) of
- undefined ->
- {X, Y, Z} = time(),
- random:seed(X, Y, Z);
- _ ->
- ok
- end,
- random:uniform(N).
+ rand:uniform(N).
erl_millisecs() ->
erl_millisecs(erlang:monotonic_time()).
diff --git a/erts/emulator/test/erts_debug_SUITE.erl b/erts/emulator/test/erts_debug_SUITE.erl
index 35677f9953..bbba829501 100644
--- a/erts/emulator/test/erts_debug_SUITE.erl
+++ b/erts/emulator/test/erts_debug_SUITE.erl
@@ -24,13 +24,13 @@
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2,
init_per_testcase/2,end_per_testcase/2,
- test_size/1,flat_size_big/1,df/1,
+ test_size/1,flat_size_big/1,df/1,term_type/1,
instructions/1]).
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- [test_size, flat_size_big, df, instructions].
+ [test_size, flat_size_big, df, instructions, term_type].
groups() ->
[].
@@ -138,6 +138,47 @@ flat_size_big_1(Term, Size0, Limit) when Size0 < Limit ->
end;
flat_size_big_1(_, _, _) -> ok.
+
+term_type(Config) when is_list(Config) ->
+ Ts = [{fixnum, 1},
+ {fixnum, -1},
+ {bignum, 1 bsl 300},
+ {bignum, -(1 bsl 300)},
+ {hfloat, 0.0},
+ {hfloat, 0.0/-1},
+ {hfloat, 1.0/(1 bsl 302)},
+ {hfloat, 1.0*(1 bsl 302)},
+ {hfloat, -1.0/(1 bsl 302)},
+ {hfloat, -1.0*(1 bsl 302)},
+ {hfloat, 3.1416},
+ {hfloat, 1.0e18},
+ {hfloat, -3.1416},
+ {hfloat, -1.0e18},
+
+ {heap_binary, <<1,2,3>>},
+ {refc_binary, <<0:(8*80)>>},
+ {sub_binary, <<5:7>>},
+
+ {flatmap, #{ a => 1}},
+ {hashmap, maps:from_list([{I,I}||I <- lists:seq(1,76)])},
+
+ {list, [1,2,3]},
+ {nil, []},
+ {tuple, {1,2,3}},
+ {tuple, {}},
+
+ {export, fun lists:sort/1},
+ {'fun', fun() -> ok end},
+ {pid, self()},
+ {atom, atom}],
+ lists:foreach(fun({E,Val}) ->
+ R = erts_internal:term_type(Val),
+ io:format("expecting term type ~w, got ~w (~p)~n", [E,R,Val]),
+ E = R
+ end, Ts),
+ ok.
+
+
df(Config) when is_list(Config) ->
P0 = pps(),
PrivDir = ?config(priv_dir, Config),
diff --git a/erts/emulator/test/evil_SUITE.erl b/erts/emulator/test/evil_SUITE.erl
index 484d2a8bf5..d28e4d9596 100644
--- a/erts/emulator/test/evil_SUITE.erl
+++ b/erts/emulator/test/evil_SUITE.erl
@@ -382,10 +382,10 @@ my_appender_1(N, T0) ->
my_appender_1(N-1, T).
seed() ->
- random:seed(3172, 9815, 20129).
+ rand:seed(exsplus, {3172,9815,20129}).
rnd_term() ->
- U0 = random:uniform(),
+ U0 = rand:uniform(),
B = <<U0/float>>,
{U0,U0 * 2.5 + 3.14,[U0*2.3,B]}.
diff --git a/erts/emulator/test/hash_SUITE.erl b/erts/emulator/test/hash_SUITE.erl
index 2ea49467b8..1b2acf48e1 100644
--- a/erts/emulator/test/hash_SUITE.erl
+++ b/erts/emulator/test/hash_SUITE.erl
@@ -223,11 +223,10 @@ basic_test() ->
range_test() ->
- random:seed(),
F = fun(From,From,_FF) ->
ok;
(From,To,FF) ->
- R = random:uniform(16#FFFFFFFFFFFFFFFF),
+ R = rand:uniform(16#FFFFFFFFFFFFFFFF),
X = erlang:phash(R, From),
Y = erlang:phash(R, 16#100000000) - 1,
Z = (Y rem From) + 1,
@@ -265,14 +264,13 @@ spread_test(N) ->
cmp_test(N) ->
- % No need to save seed, the error indicates what number caused it.
- random:seed(),
do_cmp_hashes(N,8).
+
do_cmp_hashes(0,_) ->
ok;
do_cmp_hashes(N,Steps) ->
- R0 = random:uniform(1 bsl Steps - 1) + random:uniform(16#FFFFFFFF),
- R = case random:uniform(2) of
+ R0 = rand:uniform(1 bsl Steps - 1) + rand:uniform(16#FFFFFFFF),
+ R = case rand:uniform(2) of
1 ->
R0;
_ ->
diff --git a/erts/emulator/test/map_SUITE.erl b/erts/emulator/test/map_SUITE.erl
index 886ae7d516..5e9814be60 100644
--- a/erts/emulator/test/map_SUITE.erl
+++ b/erts/emulator/test/map_SUITE.erl
@@ -58,6 +58,7 @@
%% erlang
t_erlang_hash/1,
t_map_encode_decode/1,
+ t_gc_rare_map_overflow/1,
%% non specific BIF related
t_bif_build_and_check/1,
@@ -121,6 +122,7 @@ all() -> [
%% erlang
t_erlang_hash, t_map_encode_decode,
+ t_gc_rare_map_overflow,
t_map_size, t_is_map,
%% non specific BIF related
@@ -1509,11 +1511,8 @@ t_map_equal(Config) when is_list(Config) ->
t_map_compare(Config) when is_list(Config) ->
- Seed = {erlang:monotonic_time(),
- erlang:time_offset(),
- erlang:unique_integer()},
- io:format("seed = ~p\n", [Seed]),
- random:seed(Seed),
+ rand:seed(exsplus),
+ io:format("seed = ~p\n", [rand:export_seed()]),
repeat(100, fun(_) -> float_int_compare() end, []),
repeat(100, fun(_) -> recursive_compare() end, []),
ok.
@@ -1531,7 +1530,7 @@ float_int_compare() ->
numeric_keys(N) ->
lists:foldl(fun(_,Acc) ->
- Int = random:uniform(N*4) - N*2,
+ Int = rand:uniform(N*4) - N*2,
Float = float(Int),
[Int, Float, Float * 0.99, Float * 1.01 | Acc]
end,
@@ -1562,7 +1561,7 @@ do_compare([Gen1, Gen2]) ->
%% Change one key from int to float (or vice versa) and check compare
ML1 = maps:to_list(M1),
- {K1,V1} = lists:nth(random:uniform(length(ML1)), ML1),
+ {K1,V1} = lists:nth(rand:uniform(length(ML1)), ML1),
case K1 of
I when is_integer(I) ->
case maps:find(float(I),M1) of
@@ -1653,9 +1652,9 @@ cmp_others(T1, T2, _) ->
map_gen(Pairs, Size) ->
{_,L} = lists:foldl(fun(_, {Keys, Acc}) ->
- KI = random:uniform(size(Keys)),
+ KI = rand:uniform(size(Keys)),
K = element(KI,Keys),
- KV = element(random:uniform(size(K)), K),
+ KV = element(rand:uniform(size(K)), K),
{erlang:delete_element(KI,Keys), [KV | Acc]}
end,
{Pairs, []},
@@ -1695,15 +1694,15 @@ term_gen_recursive(Leafs, Flags, Depth) ->
MaxDepth = 10,
Rnd = case {Flags, Depth} of
{_, MaxDepth} -> % Only leafs
- random:uniform(size(Leafs)) + 3;
+ rand:uniform(size(Leafs)) + 3;
{0, 0} -> % Only containers
- random:uniform(3);
+ rand:uniform(3);
{0,_} -> % Anything
- random:uniform(size(Leafs)+3)
+ rand:uniform(size(Leafs)+3)
end,
case Rnd of
1 -> % Make map
- Size = random:uniform(size(Leafs)),
+ Size = rand:uniform(size(Leafs)),
lists:foldl(fun(_, {Acc1,Acc2}) ->
{K1,K2} = term_gen_recursive(Leafs, Flags,
Depth+1),
@@ -1718,7 +1717,7 @@ term_gen_recursive(Leafs, Flags, Depth) ->
{Cdr1,Cdr2} = term_gen_recursive(Leafs, Flags, Depth+1),
{[Car1 | Cdr1], [Car2 | Cdr2]};
3 -> % Make tuple
- Size = random:uniform(size(Leafs)),
+ Size = rand:uniform(size(Leafs)),
L = lists:map(fun(_) -> term_gen_recursive(Leafs, Flags, Depth+1) end,
lists:seq(1,Size)),
{L1, L2} = lists:unzip(L),
@@ -1727,7 +1726,7 @@ term_gen_recursive(Leafs, Flags, Depth) ->
N -> % Make leaf
case element(N-3, Leafs) of
I when is_integer(I) ->
- case random:uniform(4) of
+ case rand:uniform(4) of
1 -> {I, float(I)};
2 -> {float(I), I};
_ -> {I,I}
@@ -2181,7 +2180,9 @@ t_map_encode_decode(Config) when is_list(Config) ->
{<<>>, sc9}, {3.14158, sc10},
{[3.14158], sc11}, {more_atoms, sc12},
{{more_tuples}, sc13}, {self(), sc14},
- {{},{}},{[],[]}
+ {{},{}},{[],[]},
+ {map_s, #{a=>a, 2=>b, 3=>c}},
+ {map_l, maps:from_list([{I,I}||I <- lists:seq(1,74)])}
],
ok = map_encode_decode_and_match(Pairs,[],#{}),
@@ -2245,9 +2246,30 @@ t_map_encode_decode(Config) when is_list(Config) ->
%% bad size (too small) .. should fail just truncate it .. weird.
%% possibly change external format so truncated will be #{a:=1}
- #{ a:=b } =
- erlang:binary_to_term(<<131,116,0,0,0,1,100,0,1,97,100,0,1,98,97,1,97,1>>),
-
+ #{ a:=b } = erlang:binary_to_term(<<131,116,0,0,0,1,100,0,1,97,100,0,1,98,97,1,97,1>>),
+
+ %% specific fannerl (opensource app) binary_to_term error in 18.1
+
+ #{bias := {1,1,0},
+ bit_fail := 0,
+ connections := #{{2,9} := _,
+ {8,14} := _,
+ {2,12} := _,
+ {5,7} := _,
+ {11,16} := _,
+ {11,15} := _},
+ layers := {5,7,3},
+ network_type := fann_nettype_layer,
+ num_input := 5,
+ num_layers := 3,
+ num_output := 3,
+ rprop_delta_max := _,
+ rprop_delta_min := _,
+ total_connections := 66,
+ total_neurons := 17,
+ train_error_function := fann_errorfunc_tanh,
+ train_stop_function := fann_stopfunc_mse,
+ training_algorithm := fann_train_rprop} = erlang:binary_to_term(fannerl()),
ok.
map_encode_decode_and_match([{K,V}|Pairs], EncodedPairs, M0) ->
@@ -2573,7 +2595,7 @@ hashmap_balance(KeyFun) ->
F = fun(I, {M0,Max0}) ->
Key = KeyFun(I),
M1 = M0#{Key => Key},
- Max1 = case erts_internal:map_type(M1) of
+ Max1 = case erts_internal:term_type(M1) of
hashmap ->
Nodes = hashmap_nodes(M1),
Avg = maps:size(M1) * 0.4,
@@ -2966,3 +2988,189 @@ do_badmap_17(Config) ->
%% Use this function to avoid compile-time evaluation of an expression.
id(I) -> I.
+
+
+%% OTP-13146
+%% Provoke major GC with a lot of "fat" maps on external format in msg queue
+%% causing heap fragments to be allocated.
+t_gc_rare_map_overflow(Config) ->
+ Pa = filename:dirname(code:which(?MODULE)),
+ {ok, Node} = test_server:start_node(gc_rare_map_overflow, slave, [{args, "-pa \""++Pa++"\""}]),
+ erts_debug:set_internal_state(available_internal_state, true),
+ try
+ Echo = spawn_link(Node, fun Loop() -> receive {From,Msg} -> From ! Msg
+ end,
+ Loop()
+ end),
+ FatMap = fatmap(34),
+ false = (flatmap =:= erts_internal:term_type(FatMap)),
+
+ t_gc_rare_map_overflow_do(Echo, FatMap, fun() -> erlang:garbage_collect() end),
+
+ %% Repeat test for minor gc:
+ t_gc_rare_map_overflow_do(Echo, FatMap, fun() -> minor_collect() end),
+
+ unlink(Echo),
+
+ %% Test fatmap in exit signal
+ Exiter = spawn_link(Node, fun Loop() -> receive {From,Msg} ->
+ "not_a_map" = Msg % badmatch!
+ end,
+ Loop()
+ end),
+ process_flag(trap_exit, true),
+ Exiter ! {self(), FatMap},
+ {'EXIT', Exiter, {{badmatch,FatMap}, _}} = receive M -> M end,
+ ok
+
+ after
+ process_flag(trap_exit, false),
+ erts_debug:set_internal_state(available_internal_state, false),
+ test_server:stop_node(Node)
+ end.
+
+t_gc_rare_map_overflow_do(Echo, FatMap, GcFun) ->
+ Master = self(),
+ true = receive M -> false after 0 -> true end, % assert empty msg queue
+ Echo ! {Master, token},
+ repeat(1000, fun(_) -> Echo ! {Master, FatMap} end, void),
+
+ timer:sleep(100), % Wait for maps to arrive in our msg queue
+ token = receive Tok -> Tok end, % and provoke move from outer to inner msg queue
+
+ %% Do GC that will "overflow" and create heap frags due to all the fat maps
+ GcFun(),
+
+ %% Now check that all maps in msg queueu are intact
+ %% Will crash emulator in OTP-18.1
+ repeat(1000, fun(_) -> FatMap = receive FM -> FM end end, void),
+ ok.
+
+minor_collect() ->
+ Before = minor_gcs(),
+ erts_debug:set_internal_state(force_gc, self()),
+ erlang:yield(),
+ After = minor_gcs(),
+ io:format("minor_gcs: ~p -> ~p\n", [Before, After]).
+
+minor_gcs() ->
+ {garbage_collection, Info} = process_info(self(), garbage_collection),
+ {minor_gcs, GCS} = lists:keyfind(minor_gcs, 1, Info),
+ GCS.
+
+%% Generate a map with N (or N+1) keys that has an abnormal heap demand.
+%% Done by finding keys that collide in the first 32-bit hash.
+fatmap(N) ->
+ %%erts_debug:set_internal_state(available_internal_state, true),
+ Table = ets:new(void, [bag, private]),
+
+ Seed0 = rand:seed_s(exsplus, {4711, 3141592, 2718281}),
+ Seed1 = fatmap_populate(Table, Seed0, (1 bsl 16)),
+ Keys = fatmap_generate(Table, Seed1, N, []),
+ ets:delete(Table),
+ maps:from_list([{K,K} || K <- Keys]).
+
+fatmap_populate(_, Seed, 0) -> Seed;
+fatmap_populate(Table, Seed, N) ->
+ {I, NextSeed} = rand:uniform_s(1 bsl 48, Seed),
+ Hash = internal_hash(I),
+ ets:insert(Table, [{Hash, I}]),
+ fatmap_populate(Table, NextSeed, N-1).
+
+
+fatmap_generate(_, _, N, Acc) when N =< 0 ->
+ Acc;
+fatmap_generate(Table, Seed, N0, Acc0) ->
+ {I, NextSeed} = rand:uniform_s(1 bsl 48, Seed),
+ Hash = internal_hash(I),
+ case ets:member(Table, Hash) of
+ true ->
+ NewKeys = [I | ets:lookup_element(Table, Hash, 2)],
+ Acc1 = lists:usort(Acc0 ++ NewKeys),
+ N1 = N0 - (length(Acc1) - length(Acc0)),
+ fatmap_generate(Table, NextSeed, N1, Acc1);
+ false ->
+ fatmap_generate(Table, NextSeed, N0, Acc0)
+ end.
+
+internal_hash(Term) ->
+ erts_debug:get_internal_state({internal_hash, Term}).
+
+
+%% map external_format (fannerl).
+fannerl() ->
+ <<131,116,0,0,0,28,100,0,13,108,101,97,114,110,105,110,103,95,114,
+ 97,116,101,70,63,230,102,102,96,0,0,0,100,0,17,108,101,97,114,110,105,110,
+ 103,95,109,111,109,101,110,116,117,109,70,0,0,0,0,0,0,0,0,100,0,
+ 18,116,114,97,105,110,105,110,103,95,97,108,103,111,114,105,116,104,109,100,0,
+ 16,102,97,110,110,95,116,114,97,105,110,95,114,112,114,111,112,
+ 100,0,17,109,101,97,110,95,115,113,117,97,114,101,95,101,114,114,111,114,70,
+ 0,0,0,0,0,0,0,0,100,0,8,98,105,116,95,102,97,105,108,97,0,100,0,20,
+ 116,114,97,105,110,95,101,114,114,111,114,95,102,117,110,99,116,105,111,
+ 110,100,0,19,102,97,110,110,95,101,114,114,111,114,102,117,110,99,
+ 95,116,97,110,104,100,0,9,110,117,109,95,105,110,112,117,116,97,5,100,0,10,110,
+ 117,109,95,111,117,116,112,117,116,97,3,100,0,13,116,111,116,97,108,
+ 95,110,101,117,114,111,110,115,97,17,100,0,17,116,111,116,97,108,95,99,111,110,
+ 110,101,99,116,105,111,110,115,97,66,100,0,12,110,101,116,119,111,114,107,
+ 95,116,121,112,101,100,0,18,102,97,110,110,95,110,101,116,116,121,112,101,
+ 95,108,97,121,101,114,100,0,15,99,111,110,110,101,99,116,105,111,110,95,
+ 114,97,116,101,70,63,240,0,0,0,0,0,0,100,0,10,110,117,109,95,108,97,121,101,
+ 114,115,97,3,100,0,19,116,114,97,105,110,95,115,116,111,112,95,102,117,110,
+ 99,116,105,111,110,100,0,17,102,97,110,110,95,115,116,111,112,102,117,110,
+ 99,95,109,115,101,100,0,15,113,117,105,99,107,112,114,111,112,95,100,101,99,
+ 97,121,70,191,26,54,226,224,0,0,0,100,0,12,113,117,105,99,107,112,114,
+ 111,112,95,109,117,70,63,252,0,0,0,0,0,0,100,0,21,114,112,114,111,112,95,105,
+ 110,99,114,101,97,115,101,95,102,97,99,116,111,114,70,63,243,51,51,
+ 64,0,0,0,100,0,21,114,112,114,111,112,95,100,101,99,114,101,97,115,101,
+ 95,102,97,99,116,111,114,70,63,224,0,0,0,0,0,0,100,0,15,114,112,114,111,112,
+ 95,100,101,108,116,97,95,109,105,110,70,0,0,0,0,0,0,0,0,100,0,15,114,112,114,
+ 111,112,95,100,101,108,116,97,95,109,97,120,70,64,73,0,0,0,0,0,0,100,0,
+ 16,114,112,114,111,112,95,100,101,108,116,97,95,122,101,114,111,70,63,185,153,
+ 153,160,0,0,0,100,0,26,115,97,114,112,114,111,112,95,119,101,105,103,
+ 104,116,95,100,101,99,97,121,95,115,104,105,102,116,70,192,26,147,116,192,0,0,0,
+ 100,0,35,115,97,114,112,114,111,112,95,115,116,101,112,95,101,114,
+ 114,111,114,95,116,104,114,101,115,104,111,108,100,95,102,97,99,116,111,114,70,
+ 63,185,153,153,160,0,0,0,100,0,24,115,97,114,112,114,111,112,95,115,
+ 116,101,112,95,101,114,114,111,114,95,115,104,105,102,116,70,63,246,40,245,
+ 192,0,0,0,100,0,19,115,97,114,112,114,111,112,95,116,101,109,112,101,114,
+ 97,116,117,114,101,70,63,142,184,81,224,0,0,0,100,0,6,108,97,121,101,114,115,
+ 104,3,97,5,97,7,97,3,100,0,4,98,105,97,115,104,3,97,1,97,1,97,0,100,0,11,
+ 99,111,110,110,101,99,116,105,111,110,115,116,0,0,0,66,104,2,97,0,97,6,70,
+ 191,179,51,44,64,0,0,0,104,2,97,1,97,6,70,63,178,130,90,32,0,0,0,104,2,97,2,
+ 97,6,70,63,82,90,88,0,0,0,0,104,2,97,3,97,6,70,63,162,91,63,192,0,0,0,104,2,
+ 97,4,97,6,70,191,151,70,169,0,0,0,0,104,2,97,5,97,6,70,191,117,52,222,0,0,0,
+ 0,104,2,97,0,97,7,70,63,152,240,139,0,0,0,0,104,2,97,1,97,7,70,191,166,31,
+ 187,160,0,0,0,104,2,97,2,97,7,70,191,150,70,63,0,0,0,0,104,2,97,3,97,7,70,
+ 63,152,181,126,128,0,0,0,104,2,97,4,97,7,70,63,151,187,162,128,0,0,0,104,2,
+ 97,5,97,7,70,191,143,161,101,0,0,0,0,104,2,97,0,97,8,70,191,153,102,36,128,0,
+ 0,0,104,2,97,1,97,8,70,63,160,139,250,64,0,0,0,104,2,97,2,97,8,70,63,164,62,
+ 196,64,0,0,0,104,2,97,3,97,8,70,191,178,78,209,192,0,0,0,104,2,97,4,97,8,70,
+ 191,185,19,76,224,0,0,0,104,2,97,5,97,8,70,63,183,142,196,96,0,0,0,104,2,97,0,
+ 97,9,70,63,150,104,248,0,0,0,0,104,2,97,1,97,9,70,191,164,4,100,224,0,0,0,
+ 104,2,97,2,97,9,70,191,169,42,42,224,0,0,0,104,2,97,3,97,9,70,63,145,54,78,128,0,
+ 0,0,104,2,97,4,97,9,70,63,126,243,134,0,0,0,0,104,2,97,5,97,9,70,63,177,
+ 203,25,96,0,0,0,104,2,97,0,97,10,70,63,172,104,47,64,0,0,0,104,2,97,1,97,10,
+ 70,63,161,242,193,64,0,0,0,104,2,97,2,97,10,70,63,175,208,241,192,0,0,0,104,2,
+ 97,3,97,10,70,191,129,202,161,0,0,0,0,104,2,97,4,97,10,70,63,178,151,55,32,0,0,0,
+ 104,2,97,5,97,10,70,63,137,155,94,0,0,0,0,104,2,97,0,97,11,70,191,179,
+ 106,160,0,0,0,0,104,2,97,1,97,11,70,63,184,253,164,96,0,0,0,104,2,97,2,97,11,
+ 70,191,143,30,157,0,0,0,0,104,2,97,3,97,11,70,63,153,225,140,128,0,0,0,104,
+ 2,97,4,97,11,70,63,161,35,85,192,0,0,0,104,2,97,5,97,11,70,63,175,200,55,192,
+ 0,0,0,104,2,97,0,97,12,70,191,180,116,132,96,0,0,0,104,2,97,1,97,12,70,191,
+ 165,151,152,0,0,0,0,104,2,97,2,97,12,70,191,180,197,91,160,0,0,0,104,2,97,3,97,12,
+ 70,191,91,30,160,0,0,0,0,104,2,97,4,97,12,70,63,180,251,45,32,0,0,0,
+ 104,2,97,5,97,12,70,63,165,134,77,64,0,0,0,104,2,97,6,97,14,70,63,181,56,242,96,
+ 0,0,0,104,2,97,7,97,14,70,191,165,239,234,224,0,0,0,104,2,97,8,97,14,
+ 70,191,154,65,216,128,0,0,0,104,2,97,9,97,14,70,63,150,250,236,0,0,0,0,104,2,97,
+ 10,97,14,70,191,141,105,108,0,0,0,0,104,2,97,11,97,14,70,191,152,40,
+ 165,0,0,0,0,104,2,97,12,97,14,70,63,141,159,46,0,0,0,0,104,2,97,13,97,14,70,
+ 191,183,172,137,32,0,0,0,104,2,97,6,97,15,70,63,163,26,123,192,0,0,0,104,
+ 2,97,7,97,15,70,63,176,184,106,32,0,0,0,104,2,97,8,97,15,70,63,152,234,144,
+ 0,0,0,0,104,2,97,9,97,15,70,191,172,58,70,160,0,0,0,104,2,97,10,97,15,70,
+ 63,161,211,211,192,0,0,0,104,2,97,11,97,15,70,191,148,171,120,128,0,0,0,104,
+ 2,97,12,97,15,70,63,180,117,214,224,0,0,0,104,2,97,13,97,15,70,191,104,
+ 230,216,0,0,0,0,104,2,97,6,97,16,70,63,178,53,103,96,0,0,0,104,2,97,7,97,16,
+ 70,63,170,230,232,64,0,0,0,104,2,97,8,97,16,70,191,183,45,100,192,0,0,0,
+ 104,2,97,9,97,16,70,63,184,100,97,32,0,0,0,104,2,97,10,97,16,70,63,169,174,
+ 254,64,0,0,0,104,2,97,11,97,16,70,191,119,121,234,0,0,0,0,104,2,97,12,97,
+ 16,70,63,149,12,170,128,0,0,0,104,2,97,13,97,16,70,191,144,193,191,0,0,0,0>>.
diff --git a/erts/emulator/test/message_queue_data_SUITE.erl b/erts/emulator/test/message_queue_data_SUITE.erl
new file mode 100644
index 0000000000..11481409aa
--- /dev/null
+++ b/erts/emulator/test/message_queue_data_SUITE.erl
@@ -0,0 +1,239 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2014. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(message_queue_data_SUITE).
+
+-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
+ init_per_group/2,end_per_group/2,
+ init_per_testcase/2,end_per_testcase/2]).
+-export([basic/1, process_info_messages/1]).
+
+-export([basic_test/1]).
+
+-include_lib("test_server/include/test_server.hrl").
+
+init_per_testcase(Case, Config) ->
+ ?line Dog=test_server:timetrap(test_server:minutes(2)),
+ [{watchdog, Dog}, {testcase, Case}|Config].
+
+end_per_testcase(_, Config) ->
+ Dog=?config(watchdog, Config),
+ test_server:timetrap_cancel(Dog),
+ ok.
+
+suite() -> [{ct_hooks,[ts_install_cth]}].
+
+all() ->
+ [basic, process_info_messages].
+
+groups() ->
+ [].
+
+init_per_suite(Config) ->
+%% erts_debug:set_internal_state(available_internal_state, true),
+ Config.
+
+end_per_suite(_Config) ->
+%% erts_debug:set_internal_state(available_internal_state, false),
+ ok.
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+%%
+%%
+%% Test cases
+%%
+%%
+
+basic(Config) when is_list(Config) ->
+
+ basic_test(erlang:system_info(message_queue_data)),
+
+ {ok, Node1} = start_node(Config, "+xmqd off_heap"),
+ ok = rpc:call(Node1, ?MODULE, basic_test, [off_heap]),
+ stop_node(Node1),
+
+ {ok, Node2} = start_node(Config, "+xmqd on_heap"),
+ ok = rpc:call(Node2, ?MODULE, basic_test, [on_heap]),
+ stop_node(Node2),
+
+ {ok, Node3} = start_node(Config, "+xmqd mixed"),
+ ok = rpc:call(Node3, ?MODULE, basic_test, [mixed]),
+ stop_node(Node3),
+
+ ok.
+
+is_valid_mqd_value(off_heap) ->
+ true;
+is_valid_mqd_value(on_heap) ->
+ true;
+is_valid_mqd_value(mixed) ->
+ true;
+is_valid_mqd_value(_) ->
+ false.
+
+
+basic_test(Default) ->
+
+ Default = erlang:system_info(message_queue_data),
+ true = is_valid_mqd_value(Default),
+
+ {message_queue_data, Default} = process_info(self(), message_queue_data),
+ Default = process_flag(message_queue_data, off_heap),
+ {message_queue_data, off_heap} = process_info(self(), message_queue_data),
+ off_heap = process_flag(message_queue_data, on_heap),
+ {message_queue_data, on_heap} = process_info(self(), message_queue_data),
+ on_heap = process_flag(message_queue_data, mixed),
+ {message_queue_data, mixed} = process_info(self(), message_queue_data),
+ mixed = process_flag(message_queue_data, Default),
+ {'EXIT', _} = (catch process_flag(message_queue_data, blupp)),
+
+ P1 = spawn_opt(fun () -> receive after infinity -> ok end end,
+ [link]),
+ {message_queue_data, Default} = process_info(P1, message_queue_data),
+ unlink(P1),
+ exit(P1, bye),
+
+ P2 = spawn_opt(fun () -> receive after infinity -> ok end end,
+ [link, {message_queue_data, off_heap}]),
+ {message_queue_data, off_heap} = process_info(P2, message_queue_data),
+ unlink(P2),
+ exit(P2, bye),
+
+ P3 = spawn_opt(fun () -> receive after infinity -> ok end end,
+ [link, {message_queue_data, on_heap}]),
+ {message_queue_data, on_heap} = process_info(P3, message_queue_data),
+ unlink(P3),
+ exit(P3, bye),
+
+ P4 = spawn_opt(fun () -> receive after infinity -> ok end end,
+ [link, {message_queue_data, mixed}]),
+ {message_queue_data, mixed} = process_info(P4, message_queue_data),
+ unlink(P4),
+ exit(P4, bye),
+
+ {'EXIT', _} = (catch spawn_opt(fun () -> receive after infinity -> ok end end,
+ [link, {message_queue_data, blapp}])),
+
+ ok.
+
+process_info_messages(Config) when is_list(Config) ->
+ Tester = self(),
+ P1 = spawn_opt(fun () ->
+ receive after 500 -> ok end,
+ mixed = process_flag(message_queue_data, off_heap),
+ Tester ! first,
+ receive after 500 -> ok end,
+ off_heap = process_flag(message_queue_data, on_heap),
+ Tester ! second,
+ receive after 500 -> ok end,
+ on_heap = process_flag(message_queue_data, mixed),
+ Tester ! third,
+ receive after 500 -> ok end,
+ mixed = process_flag(message_queue_data, off_heap),
+ Tester ! fourth,
+
+ receive after infinity -> ok end
+ end,
+ [link, {message_queue_data, mixed}]),
+
+ P1 ! "A",
+ receive first -> ok end,
+ P1 ! "B",
+ receive second -> ok end,
+ P1 ! "C",
+ receive third -> ok end,
+ P1 ! "D",
+ receive fourth -> ok end,
+ P1 ! "E",
+
+ {messages, ["A", "B", "C", "D", "E"]} = process_info(P1, messages),
+
+ P2 = spawn_opt(fun () ->
+ receive after 500 -> ok end,
+ mixed = process_flag(message_queue_data, off_heap),
+ Tester ! first,
+ receive after 500 -> ok end,
+ off_heap = process_flag(message_queue_data, on_heap),
+ Tester ! second,
+ receive after 500 -> ok end,
+ on_heap = process_flag(message_queue_data, mixed),
+ Tester ! third,
+ receive after 500 -> ok end,
+ mixed = process_flag(message_queue_data, off_heap),
+ Tester ! fourth,
+ receive after 500 -> ok end,
+
+ Tester ! process_info(self(), messages),
+
+ receive M1 -> M1 = "A" end,
+ receive M2 -> M2 = "B" end,
+ receive M3 -> M3 = "C" end,
+ receive M4 -> M4 = "D" end,
+ receive M5 -> M5 = "E" end,
+
+ Tester ! self()
+ end,
+ [link, {message_queue_data, mixed}]),
+
+ P2 ! "A",
+ receive first -> ok end,
+ P2 ! "B",
+ receive second -> ok end,
+ P2 ! "C",
+ receive third -> ok end,
+ P2 ! "D",
+ receive fourth -> ok end,
+ P2 ! "E",
+
+ receive
+ Msg ->
+ {messages, ["A", "B", "C", "D", "E"]} = Msg
+ end,
+
+ receive P2 -> ok end,
+
+ ok.
+
+%%
+%%
+%% helpers
+%%
+%%
+
+start_node(Config) ->
+ start_node(Config, []).
+start_node(Config, Opts) when is_list(Config), is_list(Opts) ->
+ Pa = filename:dirname(code:which(?MODULE)),
+ Name = list_to_atom(atom_to_list(?MODULE)
+ ++ "-"
+ ++ atom_to_list(?config(testcase, Config))
+ ++ "-"
+ ++ integer_to_list(erlang:system_time(seconds))
+ ++ "-"
+ ++ integer_to_list(erlang:unique_integer([positive]))),
+ ?t:start_node(Name, slave, [{args, Opts++" -pa "++Pa}]).
+
+stop_node(Node) ->
+ ?t:stop_node(Node).
diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl
index af2b955184..56b36d2626 100644
--- a/erts/emulator/test/nif_SUITE.erl
+++ b/erts/emulator/test/nif_SUITE.erl
@@ -1192,11 +1192,8 @@ send3(Config) when is_list(Config) ->
%% Let a number of processes send random message blobs between each other
%% using enif_send. Kill and spawn new ones randomly to keep a ~constant
%% number of workers running.
- Seed = {erlang:monotonic_time(),
- erlang:time_offset(),
- erlang:unique_integer()},
- io:format("seed: ~p\n",[Seed]),
- random:seed(Seed),
+ rand:seed(exsplus),
+ io:format("seed: ~p\n",[rand:export_seed()]),
ets:new(nif_SUITE,[named_table,public]),
?line true = ets:insert(nif_SUITE,{send3,0,0,0,0}),
timer:send_after(10000, timeout), % Run for 10 seconds
@@ -1229,7 +1226,7 @@ send3_controller(SpawnCnt0, Mons0, Pids0, Tick) ->
after Tick ->
Max = 20,
N = length(Pids0),
- PidN = random:uniform(Max),
+ PidN = rand:uniform(Max),
%%io:format("N=~p PidN=~p Pids0=~p\n", [N,PidN,Pids0]),
case PidN > N of
true ->
@@ -1293,7 +1290,7 @@ send3_proc(Pids0, Counters={Rcv,SndOk,SndFail}, State0) ->
end.
send3_proc_send(Pids, {Rcv,SndOk,SndFail}, State0) ->
- To = lists:nth(random:uniform(length(Pids)),Pids),
+ To = lists:nth(rand:uniform(length(Pids)),Pids),
Blob = send3_make_blob(),
State1 = send3_new_state(State0,Blob),
case send3_send(To, Blob) of
@@ -1305,12 +1302,12 @@ send3_proc_send(Pids, {Rcv,SndOk,SndFail}, State0) ->
send3_make_blob() ->
- case random:uniform(20)-1 of
+ case rand:uniform(20)-1 of
0 -> {term,[]};
N ->
MsgEnv = alloc_msgenv(),
repeat(N bsr 1,
- fun(_) -> grow_blob(MsgEnv,other_term(),random:uniform(1 bsl 20))
+ fun(_) -> grow_blob(MsgEnv,other_term(),rand:uniform(1 bsl 20))
end, void),
case (N band 1) of
0 -> {term,copy_blob(MsgEnv)};
@@ -1320,7 +1317,7 @@ send3_make_blob() ->
send3_send(Pid, Msg) ->
%% 90% enif_send and 10% normal bang
- case random:uniform(10) of
+ case rand:uniform(10) of
1 -> send3_send_bang(Pid,Msg);
_ -> send3_send_nif(Pid,Msg)
end.
@@ -1341,7 +1338,7 @@ send3_send_bang(Pid, {msgenv,MsgEnv}) ->
true.
send3_new_state(State, Blob) ->
- case random:uniform(5+2) of
+ case rand:uniform(5+2) of
N when N =< 5-> setelement(N, State, Blob);
_ -> State % Don't store blob
end.
diff --git a/erts/emulator/test/nif_SUITE_data/nif_mod.c b/erts/emulator/test/nif_SUITE_data/nif_mod.c
index 9c78c0e04d..f7e729e2b6 100644
--- a/erts/emulator/test/nif_SUITE_data/nif_mod.c
+++ b/erts/emulator/test/nif_SUITE_data/nif_mod.c
@@ -240,7 +240,7 @@ static ERL_NIF_TERM lib_version(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg
static ERL_NIF_TERM get_priv_data_ptr(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
ADD_CALL("get_priv_data_ptr");
- return enif_make_ulong(env, (unsigned long)priv_data(env));
+ return enif_make_uint64(env, (ErlNifUInt64)priv_data(env));
}
static ERL_NIF_TERM make_new_resource(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
diff --git a/erts/emulator/test/op_SUITE.erl b/erts/emulator/test/op_SUITE.erl
index 6eda78a57b..65a5a4c505 100644
--- a/erts/emulator/test/op_SUITE.erl
+++ b/erts/emulator/test/op_SUITE.erl
@@ -97,10 +97,11 @@ relop_simple(Config) when is_list(Config) ->
lists:foreach(fun({A,B}) -> relop_simple_do(A,B) end,
Combos),
- repeat(fun() -> Size = random:uniform(100),
- Rnd1 = make_rand_term(Size),
- {Rnd2,0} = clone_and_mutate(Rnd1, random:uniform(Size)),
- relop_simple_do(Rnd1,Rnd2)
+ repeat(fun() ->
+ Size = rand:uniform(100),
+ Rnd1 = make_rand_term(Size),
+ {Rnd2,0} = clone_and_mutate(Rnd1, rand:uniform(Size)),
+ relop_simple_do(Rnd1,Rnd2)
end,
1000),
ok.
@@ -158,7 +159,7 @@ cmp_emu(A,B) ->
make_rand_term(1) ->
make_rand_term_single();
make_rand_term(Arity) ->
- case random:uniform(3) of
+ case rand:uniform(3) of
1 ->
make_rand_list(Arity);
2 ->
@@ -169,17 +170,17 @@ make_rand_term(Arity) ->
end.
make_rand_term_single() ->
- Range = 1 bsl random:uniform(200),
- case random:uniform(12) of
+ Range = 1 bsl rand:uniform(200),
+ case rand:uniform(12) of
1 -> random;
2 -> uniform;
- 3 -> random:uniform(Range) - (Range div 2);
- 4 -> Range * (random:uniform() - 0.5);
+ 3 -> rand:uniform(Range) - (Range div 2);
+ 4 -> Range * (rand:uniform() - 0.5);
5 -> 0;
6 -> 0.0;
7 -> make_ref();
8 -> self();
- 9 -> term_to_binary(random:uniform(Range));
+ 9 -> term_to_binary(rand:uniform(Range));
10 -> fun(X) -> X*Range end;
11 -> fun(X) -> X/Range end;
12 -> []
@@ -188,7 +189,7 @@ make_rand_term_single() ->
make_rand_term_rand_size(1) ->
{make_rand_term(1), 0};
make_rand_term_rand_size(MaxArity) ->
- Arity = random:uniform(MaxArity-1),
+ Arity = rand:uniform(MaxArity-1),
{make_rand_term(Arity), MaxArity-Arity}.
make_rand_list(0) -> [];
diff --git a/erts/emulator/test/port_SUITE.erl b/erts/emulator/test/port_SUITE.erl
index 6f29e3ad95..ff75ee86d6 100644
--- a/erts/emulator/test/port_SUITE.erl
+++ b/erts/emulator/test/port_SUITE.erl
@@ -2269,15 +2269,14 @@ random_char(Chars) ->
lists:nth(uniform(length(Chars)), Chars).
uniform(N) ->
- case get(random_seed) of
- undefined ->
- {X, Y, Z} = Seed = time(),
- io:format("Random seed = ~p\n",[Seed]),
- random:seed(X, Y, Z);
+ case rand:export_seed() of
+ undefined ->
+ rand:seed(exsplus),
+ io:format("Random seed = ~p\n", [rand:export_seed()]);
_ ->
ok
end,
- random:uniform(N).
+ rand:uniform(N).
fun_spawn(Fun) ->
fun_spawn(Fun, []).
@@ -2417,7 +2416,7 @@ close_deaf_port(Config) when is_list(Config) ->
close_deaf_port_1(200, _) ->
ok;
close_deaf_port_1(N, Cmd) ->
- Timeout = integer_to_list(random:uniform(5*1000)),
+ Timeout = integer_to_list(rand:uniform(5*1000)),
try open_port({spawn_executable,Cmd},[{args,[Timeout]}]) of
Port ->
erlang:port_command(Port,"Hello, can you hear me!?!?"),
@@ -2458,7 +2457,7 @@ port_setget_data(Config) when is_list(Config) ->
ok.
port_setget_data_hammer(Port, HeapData, IsSet0, N) ->
- Rand = random:uniform(3),
+ Rand = rand:uniform(3),
IsSet1 = try case Rand of
1 -> true = erlang:port_set_data(Port, atom), true;
2 -> true = erlang:port_set_data(Port, HeapData), true;
diff --git a/erts/emulator/test/port_bif_SUITE.erl b/erts/emulator/test/port_bif_SUITE.erl
index b65a22a528..981899b167 100644
--- a/erts/emulator/test/port_bif_SUITE.erl
+++ b/erts/emulator/test/port_bif_SUITE.erl
@@ -485,14 +485,7 @@ random_char(Chars) ->
lists:nth(uniform(length(Chars)), Chars).
uniform(N) ->
- case get(random_seed) of
- undefined ->
- {X, Y, Z} = time(),
- random:seed(X, Y, Z);
- _ ->
- ok
- end,
- random:uniform(N).
+ rand:uniform(N).
unaligned_sub_bin(Bin0) ->
Bin1 = <<0:3,Bin0/binary,31:5>>,
diff --git a/erts/emulator/test/random_iolist.erl b/erts/emulator/test/random_iolist.erl
index 9a0f034e72..6da7da04de 100644
--- a/erts/emulator/test/random_iolist.erl
+++ b/erts/emulator/test/random_iolist.erl
@@ -36,7 +36,7 @@ run2(Iter,Fun1,Fun2) ->
compare2(Iter,Fun1,Fun2).
random_byte() ->
- random:uniform(256) - 1.
+ rand:uniform(256) - 1.
random_list(0,Acc) ->
Acc;
@@ -45,7 +45,7 @@ random_list(N,Acc) ->
random_binary(N) ->
B = list_to_binary(random_list(N,[])),
- case {random:uniform(2),size(B)} of
+ case {rand:uniform(2),size(B)} of
{2,M} when M > 1 ->
S = M-1,
<<_:3,C:S/binary,_:5>> = B,
@@ -57,7 +57,7 @@ random_list(N) ->
random_list(N,[]).
front() ->
- case random:uniform(10) of
+ case rand:uniform(10) of
10 ->
false;
_ ->
@@ -65,7 +65,7 @@ front() ->
end.
any_type() ->
- case random:uniform(10) of
+ case rand:uniform(10) of
1 ->
list;
2 ->
@@ -77,7 +77,7 @@ any_type() ->
end.
tail_type() ->
- case random:uniform(5) of
+ case rand:uniform(5) of
1 ->
list;
2 ->
@@ -90,9 +90,9 @@ random_length(N) ->
UpperLimit = 255,
case N of
M when M > UpperLimit ->
- random:uniform(UpperLimit+1) - 1;
+ rand:uniform(UpperLimit+1) - 1;
_ ->
- random:uniform(N+1) - 1
+ rand:uniform(N+1) - 1
end.
random_iolist(0,Acc) ->
@@ -139,7 +139,7 @@ random_iolist(N) ->
standard_seed() ->
- random:seed(1201,855653,380975).
+ rand:seed(exsplus, {1201,855653,380975}).
do_comp(List,F1,F2) ->
X = F1(List),
diff --git a/erts/emulator/test/save_calls_SUITE.erl b/erts/emulator/test/save_calls_SUITE.erl
index 544d841f16..810bc07eed 100644
--- a/erts/emulator/test/save_calls_SUITE.erl
+++ b/erts/emulator/test/save_calls_SUITE.erl
@@ -189,7 +189,7 @@ is_local_function(_) ->
% Number crunching for reds test.
carmichaels_below(N) ->
- random:seed(3172,9814,20125),
+ rand:seed(exsplus, {3172,9814,20125}),
carmichaels_below(1,N).
carmichaels_below(N,N2) when N >= N2 ->
@@ -219,7 +219,7 @@ expmod(Base,Exp,Mod) ->
(Base * expmod(Base,Exp - 1,Mod)) rem Mod.
uniform(N) ->
- random:uniform(N-1).
+ rand:uniform(N-1).
fermat(N) ->
R = uniform(N),
diff --git a/erts/emulator/test/system_profile_SUITE.erl b/erts/emulator/test/system_profile_SUITE.erl
index e4b6511d1f..0a0784337f 100644
--- a/erts/emulator/test/system_profile_SUITE.erl
+++ b/erts/emulator/test/system_profile_SUITE.erl
@@ -448,7 +448,7 @@ run_load(N, Pids) ->
run_load(N - 1, [Pid | Pids]).
list_load() ->
- ok = case math:sin(random:uniform(32451)) of
+ ok = case math:sin(rand:uniform(32451)) of
A when is_float(A) -> ok;
_ -> ok
end,
diff --git a/erts/emulator/test/time_SUITE.erl b/erts/emulator/test/time_SUITE.erl
index 33076c7461..3bd28a6d20 100644
--- a/erts/emulator/test/time_SUITE.erl
+++ b/erts/emulator/test/time_SUITE.erl
@@ -69,7 +69,7 @@
init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
[{testcase, Func}|Config].
-end_per_testcase(_Func, Config) ->
+end_per_testcase(_Func, _Config) ->
ok.
suite() -> [{ct_hooks,[ts_install_cth]}].
@@ -742,25 +742,21 @@ chk_strc(Res0, Res1) ->
ok.
chk_random_values(FR, TR) ->
-% case (FR rem TR == 0) orelse (TR rem FR == 0) of
-% true ->
- io:format("rand values ~p -> ~p~n", [FR, TR]),
- random:seed(268438039, 268440479, 268439161),
- Values = lists:map(fun (_) -> random:uniform(1 bsl 65) - (1 bsl 64) end,
- lists:seq(1, 100000)),
- CheckFun = fun (V) ->
- CV = erlang:convert_time_unit(V, FR, TR),
- case {(FR*CV) div TR =< V,
- (FR*(CV+1)) div TR >= V} of
- {true, true} ->
- ok;
- Failure ->
- ?t:fail({Failure, CV, V, FR, TR})
- end
- end,
- lists:foreach(CheckFun, Values).%;
-% false -> ok
-% end.
+ io:format("rand values ~p -> ~p~n", [FR, TR]),
+ rand:seed(exsplus, {268438039,268440479,268439161}),
+ Values = lists:map(fun (_) -> rand:uniform(1 bsl 65) - (1 bsl 64) end,
+ lists:seq(1, 100000)),
+ CheckFun = fun (V) ->
+ CV = erlang:convert_time_unit(V, FR, TR),
+ case {(FR*CV) div TR =< V,
+ (FR*(CV+1)) div TR >= V} of
+ {true, true} ->
+ ok;
+ Failure ->
+ ?t:fail({Failure, CV, V, FR, TR})
+ end
+ end,
+ lists:foreach(CheckFun, Values).
chk_values_per_value(_FromRes, _ToRes,
diff --git a/erts/emulator/test/trace_SUITE.erl b/erts/emulator/test/trace_SUITE.erl
index 6eae182e45..00b90e3c3d 100644
--- a/erts/emulator/test/trace_SUITE.erl
+++ b/erts/emulator/test/trace_SUITE.erl
@@ -933,7 +933,7 @@ suspend_exit(suite) ->
[];
suspend_exit(Config) when is_list(Config) ->
?line Dog = test_server:timetrap(test_server:minutes(2)),
- ?line random:seed(4711,17,4711),
+ rand:seed(exsplus, {4711,17,4711}),
?line do_suspend_exit(5000),
?line test_server:timetrap_cancel(Dog),
?line ok.
@@ -941,7 +941,7 @@ suspend_exit(Config) when is_list(Config) ->
do_suspend_exit(0) ->
?line ok;
do_suspend_exit(N) ->
- ?line Work = random:uniform(50),
+ Work = rand:uniform(50),
?line Parent = self(),
?line {Suspendee, Mon2}
= spawn_monitor(fun () ->
diff --git a/erts/epmd/src/epmd.c b/erts/epmd/src/epmd.c
index 7c373509be..21ce4e52b0 100644
--- a/erts/epmd/src/epmd.c
+++ b/erts/epmd/src/epmd.c
@@ -29,7 +29,7 @@
#ifdef HAVE_STDLIB_H
# include <stdlib.h>
#endif
-
+#include <time.h>
/* forward declarations */
static void usage(EpmdVars *);
diff --git a/erts/etc/common/ct_run.c b/erts/etc/common/ct_run.c
index 548514ee6c..11cec26264 100644
--- a/erts/etc/common/ct_run.c
+++ b/erts/etc/common/ct_run.c
@@ -83,7 +83,6 @@ static int eargc; /* Number of arguments in eargv. */
static void error(char* format, ...);
static char* emalloc(size_t size);
static char* strsave(char* string);
-static void push_words(char* src);
static int run_erlang(char* name, char** argv);
static char* get_default_emulator(char* progname);
#ifdef __WIN32__
@@ -152,6 +151,8 @@ int main(int argc, char** argv)
argv0 = argv;
emulator = get_default_emulator(argv[0]);
+ if (strlen(emulator) >= MAXPATHLEN)
+ error("Emulator path length is too large");
/*
* Allocate the argv vector to be used for arguments to Erlang.
@@ -163,7 +164,7 @@ int main(int argc, char** argv)
eargv_base = (char **) emalloc(eargv_size*sizeof(char*));
eargv = eargv_base;
eargc = 0;
- push_words(emulator);
+ PUSH(strsave(emulator));
eargc_base = eargc;
eargv = eargv + eargv_size/2;
eargc = 0;
@@ -294,26 +295,6 @@ int main(int argc, char** argv)
return run_erlang(eargv[0], eargv);
}
-static void
-push_words(char* src)
-{
- char sbuf[MAXPATHLEN];
- char* dst;
-
- dst = sbuf;
- while ((*dst++ = *src++) != '\0') {
- if (isspace((int)*src)) {
- *dst = '\0';
- PUSH(strsave(sbuf));
- dst = sbuf;
- do {
- src++;
- } while (isspace((int)*src));
- }
- }
- if (sbuf[0])
- PUSH(strsave(sbuf));
-}
#ifdef __WIN32__
wchar_t *make_commandline(char **argv)
{
diff --git a/erts/etc/common/dialyzer.c b/erts/etc/common/dialyzer.c
index c45626606c..cac1464bf6 100644
--- a/erts/etc/common/dialyzer.c
+++ b/erts/etc/common/dialyzer.c
@@ -65,7 +65,6 @@ static int eargc; /* Number of arguments in eargv. */
static void error(char* format, ...);
static char* emalloc(size_t size);
static char* strsave(char* string);
-static void push_words(char* src);
static int run_erlang(char* name, char** argv);
static char* get_default_emulator(char* progname);
#ifdef __WIN32__
@@ -189,7 +188,7 @@ int main(int argc, char** argv)
eargv_base = (char **) emalloc(eargv_size*sizeof(char*));
eargv = eargv_base;
eargc = 0;
- push_words(emulator);
+ PUSH(strsave(emulator));
eargc_base = eargc;
eargv = eargv + eargv_size/2;
eargc = 0;
@@ -269,27 +268,6 @@ int main(int argc, char** argv)
return run_erlang(eargv[0], eargv);
}
-static void
-push_words(char* src)
-{
- char sbuf[MAXPATHLEN];
- char* dst;
-
- dst = sbuf;
- while ((*dst++ = *src++) != '\0') {
- if (isspace((int)*src)) {
- *dst = '\0';
- PUSH(strsave(sbuf));
- dst = sbuf;
- do {
- src++;
- } while (isspace((int)*src));
- }
- }
- if (sbuf[0])
- PUSH(strsave(sbuf));
-}
-
#ifdef __WIN32__
wchar_t *make_commandline(char **argv)
{
diff --git a/erts/etc/common/erlc.c b/erts/etc/common/erlc.c
index f9d909e01c..049afc526a 100644
--- a/erts/etc/common/erlc.c
+++ b/erts/etc/common/erlc.c
@@ -200,7 +200,7 @@ int main(int argc, char** argv)
eargv_base = (char **) emalloc(eargv_size*sizeof(char*));
eargv = eargv_base;
eargc = 0;
- push_words(emulator);
+ PUSH(strsave(emulator));
eargc_base = eargc;
eargv = eargv + eargv_size/2;
eargc = 0;
@@ -330,26 +330,6 @@ process_opt(int* pArgc, char*** pArgv, int offset)
return argv[1];
}
-static void
-push_words(char* src)
-{
- char sbuf[MAXPATHLEN];
- char* dst;
-
- dst = sbuf;
- while ((*dst++ = *src++) != '\0') {
- if (isspace((int)*src)) {
- *dst = '\0';
- PUSH(strsave(sbuf));
- dst = sbuf;
- do {
- src++;
- } while (isspace((int)*src));
- }
- }
- if (sbuf[0])
- PUSH(strsave(sbuf));
-}
#ifdef __WIN32__
wchar_t *make_commandline(char **argv)
{
diff --git a/erts/etc/common/erlexec.c b/erts/etc/common/erlexec.c
index cde0b25a2a..f21671e837 100644
--- a/erts/etc/common/erlexec.c
+++ b/erts/etc/common/erlexec.c
@@ -73,6 +73,7 @@ static const char plusM_au_allocs[]= {
'R', /* driver_alloc */
'S', /* sl_alloc */
'T', /* temp_alloc */
+ 'Z', /* test_alloc */
'\0'
};
@@ -155,6 +156,12 @@ static char *plusr_val_switches[] = {
NULL
};
+/* +x arguments with values */
+static char *plusx_val_switches[] = {
+ "mqd",
+ NULL
+};
+
/* +z arguments with values */
static char *plusz_val_switches[] = {
"dbbl",
@@ -718,7 +725,7 @@ int main(int argc, char **argv)
* on itself here. We'll avoid doing that.
*/
if (strcmp(argv[i], "-make") == 0) {
- add_args("-noshell", "-noinput", "-s", "make", "all", NULL);
+ add_args("-noshell", "-noinput", "-s", "make", "all_or_nothing", NULL);
add_Eargs("-B");
haltAfterwards = 1;
i = argc; /* Skip rest of command line */
@@ -975,6 +982,20 @@ int main(int argc, char **argv)
add_Eargs(argv[i+1]);
i++;
break;
+ case 'x':
+ if (!is_one_of_strings(&argv[i][2], plusx_val_switches)) {
+ goto the_default;
+ } else {
+ if (i+1 >= argc
+ || argv[i+1][0] == '-'
+ || argv[i+1][0] == '+')
+ usage(argv[i]);
+ argv[i][0] = '-';
+ add_Eargs(argv[i]);
+ add_Eargs(argv[i+1]);
+ i++;
+ }
+ break;
case 'z':
if (!is_one_of_strings(&argv[i][2], plusz_val_switches)) {
goto the_default;
@@ -1175,7 +1196,7 @@ usage_aux(void)
"[+S NO_SCHEDULERS:NO_SCHEDULERS_ONLINE] "
"[+SP PERCENTAGE_SCHEDULERS:PERCENTAGE_SCHEDULERS_ONLINE] "
"[+T LEVEL] [+V] [+v] "
- "[+W<i|w|e>] [+z MISC_OPTION] [args ...]\n");
+ "[+W<i|w|e>] [+x DEFAULT_PROC_FLAGS] [+z MISC_OPTION] [args ...]\n");
exit(1);
}
diff --git a/erts/etc/common/escript.c b/erts/etc/common/escript.c
index 7fd02ed436..a5c6d0d40b 100644
--- a/erts/etc/common/escript.c
+++ b/erts/etc/common/escript.c
@@ -74,7 +74,6 @@ static void error(char* format, ...);
static char* emalloc(size_t size);
static void efree(void *p);
static char* strsave(char* string);
-static void push_words(char* src);
static int run_erlang(char* name, char** argv);
static char* get_default_emulator(char* progname);
#ifdef __WIN32__
@@ -432,7 +431,7 @@ main(int argc, char** argv)
emulator = get_default_emulator(argv[0]);
}
- if (strlen(emulator) >= PMAX)
+ if (strlen(emulator) >= MAXPATHLEN)
error("Value of environment variable ESCRIPT_EMULATOR is too large");
/*
@@ -445,7 +444,7 @@ main(int argc, char** argv)
eargv_base = (char **) emalloc(eargv_size*sizeof(char*));
eargv = eargv_base;
eargc = 0;
- push_words(emulator);
+ PUSH(strsave(emulator));
eargc_base = eargc;
eargv = eargv + eargv_size/2;
eargc = 0;
@@ -554,26 +553,6 @@ main(int argc, char** argv)
return run_erlang(eargv[0], eargv);
}
-static void
-push_words(char* src)
-{
- char sbuf[PMAX];
- char* dst;
-
- dst = sbuf;
- while ((*dst++ = *src++) != '\0') {
- if (isspace((int)*src)) {
- *dst = '\0';
- PUSH(strsave(sbuf));
- dst = sbuf;
- do {
- src++;
- } while (isspace((int)*src));
- }
- }
- if (sbuf[0])
- PUSH(strsave(sbuf));
-}
#ifdef __WIN32__
wchar_t *make_commandline(char **argv)
{
diff --git a/erts/etc/common/heart.c b/erts/etc/common/heart.c
index 01ef840b5d..9571b83ffd 100644
--- a/erts/etc/common/heart.c
+++ b/erts/etc/common/heart.c
@@ -718,14 +718,12 @@ do_terminate(int erlin_fd, int reason) {
print_error("Would reboot. Terminating.");
else {
kill_old_erlang();
- /* suppress gcc warning with 'if' */
ret = system(command);
print_error("Executed \"%s\" -> %d. Terminating.",command, ret);
}
free_env_val(command);
} else {
kill_old_erlang();
- /* suppress gcc warning with 'if' */
ret = system((char*)&cmd[0]);
print_error("Executed \"%s\" -> %d. Terminating.",cmd, ret);
}
diff --git a/erts/etc/common/typer.c b/erts/etc/common/typer.c
index 0aa0996808..7ff8aa76e2 100644
--- a/erts/etc/common/typer.c
+++ b/erts/etc/common/typer.c
@@ -65,7 +65,6 @@ static int eargc; /* Number of arguments in eargv. */
static void error(char* format, ...);
static char* emalloc(size_t size);
static char* strsave(char* string);
-static void push_words(char* src);
static int run_erlang(char* name, char** argv);
static char* get_default_emulator(char* progname);
#ifdef __WIN32__
@@ -129,6 +128,9 @@ main(int argc, char** argv)
emulator = get_default_emulator(argv[0]);
+ if (strlen(emulator) >= MAXPATHLEN)
+ error("Emulator path length is too large");
+
/*
* Allocate the argv vector to be used for arguments to Erlang.
* Arrange for starting to pushing information in the middle of
@@ -139,7 +141,7 @@ main(int argc, char** argv)
eargv_base = (char **) emalloc(eargv_size*sizeof(char*));
eargv = eargv_base;
eargc = 0;
- push_words(emulator);
+ PUSH(strsave(emulator));
eargc_base = eargc;
eargv = eargv + eargv_size/2;
eargc = 0;
@@ -192,26 +194,6 @@ main(int argc, char** argv)
return run_erlang(eargv[0], eargv);
}
-static void
-push_words(char* src)
-{
- char sbuf[MAXPATHLEN];
- char* dst;
-
- dst = sbuf;
- while ((*dst++ = *src++) != '\0') {
- if (isspace((int)*src)) {
- *dst = '\0';
- PUSH(strsave(sbuf));
- dst = sbuf;
- do {
- src++;
- } while (isspace((int)*src));
- }
- }
- if (sbuf[0])
- PUSH(strsave(sbuf));
-}
#ifdef __WIN32__
wchar_t *make_commandline(char **argv)
{
diff --git a/erts/include/internal/ethread.h b/erts/include/internal/ethread.h
index 899aa4ad3c..4eeb7097f4 100644
--- a/erts/include/internal/ethread.h
+++ b/erts/include/internal/ethread.h
@@ -54,7 +54,8 @@
#endif
#if defined(ETHR_DEBUG) || !defined(ETHR_INLINE) || ETHR_XCHK \
- || (defined(__GNUC__) && defined(ERTS_MIXED_CYGWIN_VC))
+ || (defined(__GNUC__) && defined(ERTS_MIXED_CYGWIN_VC)) \
+ || (defined(__GNUC__) && defined(ERTS_MIXED_MSYS_VC))
# undef ETHR_INLINE
# define ETHR_INLINE
# undef ETHR_FORCE_INLINE
diff --git a/erts/preloaded/ebin/erl_prim_loader.beam b/erts/preloaded/ebin/erl_prim_loader.beam
index df12c6f8e0..e94a1ba796 100644
--- a/erts/preloaded/ebin/erl_prim_loader.beam
+++ b/erts/preloaded/ebin/erl_prim_loader.beam
Binary files differ
diff --git a/erts/preloaded/ebin/erlang.beam b/erts/preloaded/ebin/erlang.beam
index 863a5e61ef..632defdb46 100644
--- a/erts/preloaded/ebin/erlang.beam
+++ b/erts/preloaded/ebin/erlang.beam
Binary files differ
diff --git a/erts/preloaded/ebin/erts_internal.beam b/erts/preloaded/ebin/erts_internal.beam
index dc8c711e1a..fd0a502d2c 100644
--- a/erts/preloaded/ebin/erts_internal.beam
+++ b/erts/preloaded/ebin/erts_internal.beam
Binary files differ
diff --git a/erts/preloaded/ebin/init.beam b/erts/preloaded/ebin/init.beam
index 851513b2e9..60c08819eb 100644
--- a/erts/preloaded/ebin/init.beam
+++ b/erts/preloaded/ebin/init.beam
Binary files differ
diff --git a/erts/preloaded/ebin/otp_ring0.beam b/erts/preloaded/ebin/otp_ring0.beam
index 33c112f4de..04814c091b 100644
--- a/erts/preloaded/ebin/otp_ring0.beam
+++ b/erts/preloaded/ebin/otp_ring0.beam
Binary files differ
diff --git a/erts/preloaded/ebin/prim_eval.beam b/erts/preloaded/ebin/prim_eval.beam
index ebca6e7eea..7779c8374d 100644
--- a/erts/preloaded/ebin/prim_eval.beam
+++ b/erts/preloaded/ebin/prim_eval.beam
Binary files differ
diff --git a/erts/preloaded/ebin/prim_file.beam b/erts/preloaded/ebin/prim_file.beam
index e8817d183e..254b0e5b90 100644
--- a/erts/preloaded/ebin/prim_file.beam
+++ b/erts/preloaded/ebin/prim_file.beam
Binary files differ
diff --git a/erts/preloaded/ebin/prim_inet.beam b/erts/preloaded/ebin/prim_inet.beam
index 357bcd3d9a..b7cfe26462 100644
--- a/erts/preloaded/ebin/prim_inet.beam
+++ b/erts/preloaded/ebin/prim_inet.beam
Binary files differ
diff --git a/erts/preloaded/ebin/prim_zip.beam b/erts/preloaded/ebin/prim_zip.beam
index 969239be98..6b5c6195c8 100644
--- a/erts/preloaded/ebin/prim_zip.beam
+++ b/erts/preloaded/ebin/prim_zip.beam
Binary files differ
diff --git a/erts/preloaded/ebin/zlib.beam b/erts/preloaded/ebin/zlib.beam
index 281f668f8c..43d7b436be 100644
--- a/erts/preloaded/ebin/zlib.beam
+++ b/erts/preloaded/ebin/zlib.beam
Binary files differ
diff --git a/erts/preloaded/src/erlang.erl b/erts/preloaded/src/erlang.erl
index 4c22c596eb..9517acd78e 100644
--- a/erts/preloaded/src/erlang.erl
+++ b/erts/preloaded/src/erlang.erl
@@ -91,7 +91,7 @@
-export([bit_size/1, bitsize/1, bitstring_to_list/1]).
-export([bump_reductions/1, byte_size/1, call_on_load_function/1]).
-export([cancel_timer/1, cancel_timer/2, check_old_code/1, check_process_code/2,
- check_process_code/3, crc32/1]).
+ check_process_code/3, copy_literals/2, crc32/1]).
-export([crc32/2, crc32_combine/3, date/0, decode_packet/3]).
-export([delete_element/2]).
-export([delete_module/1, demonitor/1, demonitor/2, display/1]).
@@ -520,6 +520,13 @@ get_cpc_opts([{allow_gc, AllowGC} | Options], Async, _OldAllowGC) ->
get_cpc_opts([], Async, AllowGC) ->
{Async, AllowGC}.
+%% copy_literals/2
+-spec erlang:copy_literals(Module,Bool) -> 'true' | 'false' | 'aborted' when
+ Module :: module(),
+ Bool :: boolean().
+copy_literals(_Mod, _Bool) ->
+ erlang:nif_error(undefined).
+
%% crc32/1
-spec erlang:crc32(Data) -> non_neg_integer() when
Data :: iodata().
@@ -2039,6 +2046,9 @@ open_port(PortName, PortSettings) ->
-type priority_level() ::
low | normal | high | max.
+-type message_queue_data() ::
+ off_heap | on_heap | mixed.
+
-spec process_flag(trap_exit, Boolean) -> OldBoolean when
Boolean :: boolean(),
OldBoolean :: boolean();
@@ -2051,6 +2061,9 @@ open_port(PortName, PortSettings) ->
(min_bin_vheap_size, MinBinVHeapSize) -> OldMinBinVHeapSize when
MinBinVHeapSize :: non_neg_integer(),
OldMinBinVHeapSize :: non_neg_integer();
+ (message_queue_data, MQD) -> OldMQD when
+ MQD :: message_queue_data(),
+ OldMQD :: message_queue_data();
(priority, Level) -> OldLevel when
Level :: priority_level(),
OldLevel :: priority_level();
@@ -2089,6 +2102,7 @@ process_flag(_Flag, _Value) ->
min_bin_vheap_size |
monitored_by |
monitors |
+ message_queue_data |
priority |
reductions |
registered_name |
@@ -2130,6 +2144,7 @@ process_flag(_Flag, _Value) ->
{monitors,
Monitors :: [{process, Pid :: pid() |
{RegName :: atom(), Node :: node()}}]} |
+ {message_queue_data, MQD :: message_queue_data()} |
{priority, Level :: priority_level()} |
{reductions, Number :: non_neg_integer()} |
{registered_name, Atom :: atom()} |
@@ -2432,6 +2447,7 @@ tuple_to_list(_Tuple) ->
(multi_scheduling) -> disabled | blocked | enabled;
(multi_scheduling_blockers) -> [Pid :: pid()];
(nif_version) -> string();
+ (message_queue_data) -> message_queue_data();
(otp_release) -> string();
(os_monotonic_time_source) -> [{atom(),term()}];
(os_system_time_source) -> [{atom(),term()}];
@@ -2559,14 +2575,19 @@ spawn_monitor(M, F, A) when erlang:is_atom(M),
spawn_monitor(M, F, A) ->
erlang:error(badarg, [M,F,A]).
+
+-type spawn_opt_option() ::
+ link
+ | monitor
+ | {priority, Level :: priority_level()}
+ | {fullsweep_after, Number :: non_neg_integer()}
+ | {min_heap_size, Size :: non_neg_integer()}
+ | {min_bin_vheap_size, VSize :: non_neg_integer()}
+ | {message_queue_data, MQD :: message_queue_data()}.
+
-spec spawn_opt(Fun, Options) -> pid() | {pid(), reference()} when
Fun :: function(),
- Options :: [Option],
- Option :: link | monitor
- | {priority, Level :: priority_level()}
- | {fullsweep_after, Number :: non_neg_integer()}
- | {min_heap_size, Size :: non_neg_integer()}
- | {min_bin_vheap_size, VSize :: non_neg_integer()}.
+ Options :: [spawn_opt_option()].
spawn_opt(F, O) when erlang:is_function(F) ->
spawn_opt(erlang, apply, [F, []], O);
spawn_opt({M,F}=MF, O) when erlang:is_atom(M), erlang:is_atom(F) ->
@@ -2579,12 +2600,7 @@ spawn_opt(F, O) ->
-spec spawn_opt(Node, Fun, Options) -> pid() | {pid(), reference()} when
Node :: node(),
Fun :: function(),
- Options :: [Option],
- Option :: link | monitor
- | {priority, Level :: priority_level()}
- | {fullsweep_after, Number :: non_neg_integer()}
- | {min_heap_size, Size :: non_neg_integer()}
- | {min_bin_vheap_size, VSize :: non_neg_integer()}.
+ Options :: [spawn_opt_option()].
spawn_opt(N, F, O) when N =:= erlang:node() ->
spawn_opt(F, O);
spawn_opt(N, F, O) when erlang:is_function(F) ->
@@ -2671,12 +2687,7 @@ spawn_link(N,M,F,A) ->
Module :: module(),
Function :: atom(),
Args :: [term()],
- Options :: [Option],
- Option :: link | monitor
- | {priority, Level :: priority_level()}
- | {fullsweep_after, Number :: non_neg_integer()}
- | {min_heap_size, Size :: non_neg_integer()}
- | {min_bin_vheap_size, VSize :: non_neg_integer()}.
+ Options :: [spawn_opt_option()].
spawn_opt(M, F, A, Opts) ->
case catch erlang:spawn_opt({M,F,A,Opts}) of
{'EXIT',{Reason,_}} ->
@@ -2691,12 +2702,7 @@ spawn_opt(M, F, A, Opts) ->
Module :: module(),
Function :: atom(),
Args :: [term()],
- Options :: [Option],
- Option :: link | monitor
- | {priority, Level :: priority_level()}
- | {fullsweep_after, Number :: non_neg_integer()}
- | {min_heap_size, Size :: non_neg_integer()}
- | {min_bin_vheap_size, VSize :: non_neg_integer()}.
+ Options :: [spawn_opt_option()].
spawn_opt(N, M, F, A, O) when N =:= erlang:node(),
erlang:is_atom(M), erlang:is_atom(F),
erlang:is_list(A), erlang:is_list(O) ->
diff --git a/erts/preloaded/src/erts_internal.erl b/erts/preloaded/src/erts_internal.erl
index 81202ed3e2..426749264f 100644
--- a/erts/preloaded/src/erts_internal.erl
+++ b/erts/preloaded/src/erts_internal.erl
@@ -31,7 +31,7 @@
-export([await_port_send_result/3]).
-export([cmp_term/2]).
--export([map_to_tuple_keys/1, map_type/1, map_hashmap_children/1]).
+-export([map_to_tuple_keys/1, term_type/1, map_hashmap_children/1]).
-export([open_port/2, port_command/3, port_connect/2, port_close/1,
port_control/3, port_call/3, port_info/1, port_info/2]).
@@ -222,12 +222,18 @@ cmp_term(_A,_B) ->
map_to_tuple_keys(_M) ->
erlang:nif_error(undefined).
-%% return the internal map type
--spec map_type(M) -> Type when
- M :: map(),
- Type :: 'flatmap' | 'hashmap' | 'hashmap_node'.
-
-map_type(_M) ->
+%% return the internal term type
+-spec term_type(T) -> Type when
+ T :: term(),
+ Type :: 'flatmap' | 'hashmap' | 'hashmap_node'
+ | 'fixnum' | 'bignum' | 'hfloat'
+ | 'list' | 'tuple' | 'export' | 'fun'
+ | 'refc_binary' | 'heap_binary' | 'sub_binary'
+ | 'reference' | 'external_reference'
+ | 'pid' | 'external_pid' | 'port' | 'external_port'
+ | 'atom' | 'catch' | 'nil'.
+
+term_type(_T) ->
erlang:nif_error(undefined).
%% return the internal hashmap sub-nodes from
diff --git a/erts/preloaded/src/init.erl b/erts/preloaded/src/init.erl
index c4e37b76f1..0ad5824ad1 100644
--- a/erts/preloaded/src/init.erl
+++ b/erts/preloaded/src/init.erl
@@ -167,7 +167,6 @@ stop(Status) -> init ! {stop,{stop,Status}}, ok.
boot(BootArgs) ->
register(init, self()),
process_flag(trap_exit, true),
- start_on_load_handler_process(),
{Start0,Flags,Args} = parse_boot_args(BootArgs),
Start = map(fun prepare_run_args/1, Start0),
Flags0 = flags_to_atoms_again(Flags),
@@ -225,6 +224,7 @@ code_path_choice() ->
end.
boot(Start,Flags,Args) ->
+ start_on_load_handler_process(),
BootPid = do_boot(Flags,Start),
State = #state{flags = Flags,
args = Args,
diff --git a/erts/preloaded/src/prim_inet.erl b/erts/preloaded/src/prim_inet.erl
index d5c8fd4268..bd74831bb7 100644
--- a/erts/preloaded/src/prim_inet.erl
+++ b/erts/preloaded/src/prim_inet.erl
@@ -232,7 +232,7 @@ bindx(S, AddFlag, Addrs) ->
%% if timeout is given:
%% timeout < 0 -> infinity
%% 0 -> immediate connect (mostly works for loopback)
-%% > 0 -> wait for timout ms if not connected then
+%% > 0 -> wait for timeout ms if not connected then
%% return {error, timeout}
%%
%% ASYNC_CONNECT(insock(), IP, Port, Timeout) -> {ok, S, Ref} | {error, Reason}
@@ -273,7 +273,7 @@ async_connect(S, IP, Port, Time) ->
%% if timeout is given:
%% timeout < 0 -> infinity
%% 0 -> immediate accept (poll)
-%% > 0 -> wait for timout ms for accept if no accept then
+%% > 0 -> wait for timeout ms for accept if no accept then
%% return {error, timeout}
%%
%% ASYNC_ACCEPT(insock(), Timeout)
diff --git a/erts/test/ethread_SUITE.erl b/erts/test/ethread_SUITE.erl
index 4a40dbb11e..388af66b23 100644
--- a/erts/test/ethread_SUITE.erl
+++ b/erts/test/ethread_SUITE.erl
@@ -123,38 +123,6 @@ try_lock_mutex(suite) ->
try_lock_mutex(Config) ->
run_case(Config, "try_lock_mutex", "").
-%% Remove dead code?
-
-% wd_dispatch(P) ->
-% receive
-% bye ->
-% ?line true = port_command(P, "-1 "),
-% ?line bye;
-% L when is_list(L) ->
-% ?line true = port_command(P, L),
-% ?line wd_dispatch(P)
-% end.
-%
-% watchdog(Port) ->
-% ?line process_flag(priority, max),
-% ?line receive after 500 -> ok end,
-%
-% ?line random:seed(),
-% ?line true = port_command(Port, "0 "),
-% ?line lists:foreach(fun (T) ->
-% erlang:send_after(T,
-% self(),
-% integer_to_list(T)
-% ++ " ")
-% end,
-% lists:usort(lists:map(fun (_) ->
-% random:uniform(4500)+500
-% end,
-% lists:duplicate(50,0)))),
-% ?line erlang:send_after(5100, self(), bye),
-%
-% wd_dispatch(Port).
-
cond_wait(doc) ->
["Tests ethr_cond_wait with ethr_cond_signal and ethr_cond_broadcast."];
cond_wait(suite) ->
diff --git a/erts/test/run_erl_SUITE.erl b/erts/test/run_erl_SUITE.erl
index 328477d870..6759d41a2b 100644
--- a/erts/test/run_erl_SUITE.erl
+++ b/erts/test/run_erl_SUITE.erl
@@ -141,12 +141,10 @@ heavier_1(Config) ->
?line ToErl = open_port({spawn,"to_erl "++Pipe}, []),
io:format("ToErl = ~p\n", [ToErl]),
- X = 1,
- Y = 555,
- Z = 42,
- ?line random:seed(X, Y, Z),
- SeedCmd = lists:flatten(io_lib:format("random:seed(~p, ~p, ~p). \r\n",
- [X,Y,Z])),
+ Seed = {1,555,42},
+ rand:seed(exsplus, Seed),
+ SeedCmd = lists:flatten(io_lib:format("rand:seed(exsplus, ~p). \r\n",
+ [Seed])),
?line io:format("~p\n", [SeedCmd]),
?line erlang:port_command(ToErl, SeedCmd),
@@ -157,9 +155,9 @@ heavier_1(Config) ->
"F = fun(F,0) -> ok; "++
"(F,N) -> " ++
"io:format(\"\\\"~s\\\"~n\","++
- "[[35|[random:uniform(25)+65 || " ++
+ "[[35|[rand:uniform(25)+65 || " ++
"_ <- lists:seq(1, "++
- "random:uniform("++
+ "rand:uniform("++
integer_to_list(MaxLen)++
"))]]]), "++
"F(F,N-1) "++
@@ -189,8 +187,8 @@ receive_all(Iter, ToErl, MaxLen) ->
receive_all_1(0, _, _, _) -> ok;
receive_all_1(Iter, Line, ToErl, MaxLen) ->
- NumChars = random:uniform(MaxLen),
- Pattern = [random:uniform(25)+65 || _ <- lists:seq(1, NumChars)],
+ NumChars = rand:uniform(MaxLen),
+ Pattern = [rand:uniform(25)+65 || _ <- lists:seq(1, NumChars)],
receive_all_2(Iter, {NumChars,Pattern}, Line, ToErl, MaxLen).
diff --git a/lib/asn1/src/asn1ct_value.erl b/lib/asn1/src/asn1ct_value.erl
index 7f20d57b1e..61a5661a11 100644
--- a/lib/asn1/src/asn1ct_value.erl
+++ b/lib/asn1/src/asn1ct_value.erl
@@ -353,10 +353,7 @@ random_unnamed_bit_string(M, C) ->
%% end.
random(Upper) ->
- _ = random:seed(erlang:phash2([erlang:node()]),
- erlang:monotonic_time(),
- erlang:unique_integer()),
- random:uniform(Upper).
+ rand:uniform(Upper).
size_random(C) ->
case get_constraint(C,'SizeConstraint') of
diff --git a/lib/asn1/src/asn1rtt_ber.erl b/lib/asn1/src/asn1rtt_ber.erl
index 39fa8aaf99..e50b14941c 100644
--- a/lib/asn1/src/asn1rtt_ber.erl
+++ b/lib/asn1/src/asn1rtt_ber.erl
@@ -739,6 +739,8 @@ encode_named_bit_string([H|_]=Bits, NamedBitList, TagIn) when is_atom(H) ->
do_encode_named_bit_string(Bits, NamedBitList, TagIn);
encode_named_bit_string([{bit,_}|_]=Bits, NamedBitList, TagIn) ->
do_encode_named_bit_string(Bits, NamedBitList, TagIn);
+encode_named_bit_string([], _NamedBitList, TagIn) ->
+ encode_unnamed_bit_string(<<>>, TagIn);
encode_named_bit_string(Bits, _NamedBitList, TagIn) when is_bitstring(Bits) ->
encode_unnamed_bit_string(Bits, TagIn).
@@ -746,6 +748,8 @@ encode_named_bit_string(C, [H|_]=Bits, NamedBitList, TagIn) when is_atom(H) ->
do_encode_named_bit_string(C, Bits, NamedBitList, TagIn);
encode_named_bit_string(C, [{bit,_}|_]=Bits, NamedBitList, TagIn) ->
do_encode_named_bit_string(C, Bits, NamedBitList, TagIn);
+encode_named_bit_string(C, [], _NamedBitList, TagIn) ->
+ encode_unnamed_bit_string(C, <<>>, TagIn);
encode_named_bit_string(C, Bits, _NamedBitList, TagIn) when is_bitstring(Bits) ->
encode_unnamed_bit_string(C, Bits, TagIn).
diff --git a/lib/asn1/test/testPrimStrings.erl b/lib/asn1/test/testPrimStrings.erl
index fa778765b1..c9217d60fa 100644
--- a/lib/asn1/test/testPrimStrings.erl
+++ b/lib/asn1/test/testPrimStrings.erl
@@ -54,7 +54,7 @@ fragmented_strings(Len, Types) ->
ok.
make_ns_value(0) -> [];
-make_ns_value(N) -> [($0 - 1) + random:uniform(10)|make_ns_value(N-1)].
+make_ns_value(N) -> [($0 - 1) + rand:uniform(10)|make_ns_value(N-1)].
fragmented_lengths() ->
K16 = 1 bsl 14,
@@ -123,6 +123,7 @@ bit_string(Rules, Opts) ->
%% Bs2 ::= BIT STRING {su(0), mo(1), tu(2), we(3), th(4), fr(5), sa(6) } (SIZE (7))
%%==========================================================
+ roundtrip('Bs2', []),
roundtrip('Bs2', [mo,tu,fr]),
bs_roundtrip('Bs2', <<2#0110010:7>>, [mo,tu,fr]),
bs_roundtrip('Bs2', <<2#0110011:7>>, [mo,tu,fr,sa]),
@@ -131,6 +132,7 @@ bit_string(Rules, Opts) ->
%% Bs3 ::= BIT STRING {su(0), mo(1), tu(2), we(3), th(4), fr(5), sa(6) } (SIZE (1..7))
%%==========================================================
+ roundtrip('Bs3', []),
roundtrip('Bs3', [mo,tu,fr]),
bs_roundtrip('Bs3', <<2#0110010:7>>, [mo,tu,fr]),
bs_roundtrip('Bs3', <<2#0110010:7>>, [mo,tu,fr]),
@@ -139,6 +141,13 @@ bit_string(Rules, Opts) ->
bs_roundtrip('Bs3', <<2#11:2>>, [su,mo]),
%%==========================================================
+ %% Bs4 ::= BIT STRING {su(0), mo(1), tu(2), we(3), th(4), fr(5), sa(6) }
+ %%==========================================================
+
+ roundtrip('Bs4', []),
+ roundtrip('Bs4', [mo,tu,fr,sa]),
+
+ %%==========================================================
%% Bs7 ::= BIT STRING (SIZE (24))
%%==========================================================
diff --git a/lib/common_test/doc/src/ct_hooks_chapter.xml b/lib/common_test/doc/src/ct_hooks_chapter.xml
index d9892c66f7..3905e23dcc 100644
--- a/lib/common_test/doc/src/ct_hooks_chapter.xml
+++ b/lib/common_test/doc/src/ct_hooks_chapter.xml
@@ -30,8 +30,8 @@
<file>ct_hooks_chapter.xml</file>
</header>
- <marker id="general"></marker>
<section>
+ <marker id="general"></marker>
<title>General</title>
<p>
The <em>Common Test Hook</em> (henceforth called CTH) framework allows
@@ -60,8 +60,8 @@
</section>
- <marker id="installing"></marker>
<section>
+ <marker id="installing"></marker>
<title>Installing a CTH</title>
<p>There are multiple ways to install a CTH in your test run. You can do it
for all tests in a run, for specific test suites and for specific groups
@@ -120,8 +120,8 @@
</section>
</section>
- <marker id="scope"/>
<section>
+ <marker id="scope"/>
<title>CTH Scope</title>
<p>Once the CTH is installed into a certain test run it will be there until
its scope is expired. The scope of a CTH depends on when it is
@@ -208,8 +208,8 @@
</section>
- <marker id="manipulating"/>
<section>
+ <marker id="manipulating"/>
<title>Manipulating tests</title>
<p>It is through CTHs possible to manipulate the results of tests and
configuration functions. The main purpose of doing this with CTHs is to
@@ -226,8 +226,8 @@
makes it possible to use hooks as configuration fallbacks, or even
completely replace all configuration functions with hook functions.</p>
- <marker id="pre"/>
<section>
+ <marker id="pre"/>
<title>Pre Hooks</title>
<p>
It is possible in a CTH to hook in behaviour before
@@ -263,8 +263,8 @@
</section>
- <marker id="post"/>
<section>
+ <marker id="post"/>
<title>Post Hooks</title>
<p>It is also possible in a CTH to hook in behaviour after
<seealso marker="common_test#Module:init_per_suite-1">init_per_suite</seealso>,
@@ -308,8 +308,8 @@ post_end_per_testcase(_TC, Config, Return, CTHState) -&gt;
</section>
- <marker id="skip_n_fail"/>
<section>
+ <marker id="skip_n_fail"/>
<title>Skip and Fail hooks</title>
<p>
After any post hook has been executed for all installed CTHs,
@@ -323,8 +323,8 @@ post_end_per_testcase(_TC, Config, Return, CTHState) -&gt;
</section>
- <marker id="synchronizing"/>
<section>
+ <marker id="synchronizing"/>
<title>Synchronizing external user applications with Common Test</title>
<p>CTHs can be used to synchronize test runs with external user applications.
The init function may e.g. start and/or communicate with an application that
@@ -351,8 +351,8 @@ post_end_per_testcase(_TC, Config, Return, CTHState) -&gt;
</p>
</section>
- <marker id="example"/>
<section>
+ <marker id="example"/>
<title>Example CTH</title>
<p>The CTH below will log information about a test run into a format
parseable by <seealso marker="kernel:file#consult-1">file:consult/1</seealso>.
@@ -455,8 +455,8 @@ terminate(State) ->
ok.</code>
</section>
- <marker id="builtin_cths"/>
<section>
+ <marker id="builtin_cths"/>
<title>Built-in CTHs</title>
<p>Common Test is delivered with a couple of general purpose CTHs that
can be enabled by the user to provide some generic testing functionality.
diff --git a/lib/common_test/doc/src/event_handler_chapter.xml b/lib/common_test/doc/src/event_handler_chapter.xml
index cb7033b196..78e5bb5e70 100644
--- a/lib/common_test/doc/src/event_handler_chapter.xml
+++ b/lib/common_test/doc/src/event_handler_chapter.xml
@@ -194,8 +194,9 @@
the current test case log file.
</p></item>
- <marker id="tc_done"/>
- <item><c>#event{name = tc_done, data = {Suite,FuncOrGroup,Result}}</c>
+ <item>
+ <marker id="tc_done"/>
+ <c>#event{name = tc_done, data = {Suite,FuncOrGroup,Result}}</c>
<p><c>Suite = atom()</c>, name of the suite.</p>
<p><c>FuncOrGroup = Func | {Conf,GroupName,GroupProperties}</c></p>
<p><c>Func = atom()</c>, name of test case or configuration function.</p>
diff --git a/lib/common_test/doc/src/notes.xml b/lib/common_test/doc/src/notes.xml
index aaf6dffc88..6972d18dfc 100644
--- a/lib/common_test/doc/src/notes.xml
+++ b/lib/common_test/doc/src/notes.xml
@@ -760,7 +760,7 @@
configuration function or test specification term), the
affected test cases get the status <c>user_skipped</c>
instead.</p> <p>This update has meant a few changes that
- may affect Common Test users in various ways: <list>
+ may affect Common Test users in various ways:</p> <list>
<item>The test results and statistics will be affected,
which is important to know when running regression tests
and comparing results to previous test runs.</item>
@@ -780,7 +780,7 @@
<c>auto_skipped</c> rather than <c>user_skipped</c> as
before.</item> <item>The event messages that Common Test
generates during test runs have been affected by this
- update. For details see OTP-11524.</item> </list> </p>
+ update. For details see OTP-11524.</item> </list>
<p>
Own Id: OTP-11305 Aux Id: OTP-11524 </p>
</item>
@@ -831,7 +831,7 @@
<item>
<p>The following modifications have been made to the
event messages that Common Test sends during test
- execution: <list> <item>For the <c>tc_auto_skip</c>
+ execution:</p> <list> <item>For the <c>tc_auto_skip</c>
event, the value of the <c>Func</c> element has changed
from <c>end_per_group</c> to
<c>{end_per_group,GroupName}</c>.</item> <item>When
@@ -843,7 +843,7 @@
configuration name already in use, the <c>tc_done</c>
event now reports the error with a tuple (of size 2)
tagged <c>failed</c> instead of <c>skipped</c>.</item>
- </list> Please see the Event Handling chapter in the
+ </list> <p>Please see the Event Handling chapter in the
Common Test User's Guide for reference. </p>
<p>
Own Id: OTP-11524 Aux Id: OTP-11305 </p>
@@ -1247,7 +1247,6 @@
<item>
<p>
Some bugfixes in <c>ct_snmp:</c></p>
- <p>
<list> <item> ct_snmp will now use the value of the
'agent_vsns' config variable when setting the 'variables'
parameter to snmp application agent configuration.
@@ -1255,14 +1254,13 @@
supported versions had to be specified twice. </item>
<item> Snmp application failed to write notify.conf since
ct_snmp gave the notify type as a string instead of an
- atom. This has been corrected. </item> </list></p>
+ atom. This has been corrected. </item> </list>
<p>
Own Id: OTP-10432</p>
</item>
<item>
<p>
Some bugfixes in <c>ct_snmp</c>:</p>
- <p>
<list> <item> Functions <c>register_users/2</c>,
<c>register_agents/2</c> and <c>register_usm_users/2</c>,
and the corresponding <c>unregister_*/1</c> functions
@@ -1279,7 +1277,7 @@
priv_dir instead of in the configuration dir
(priv_dir/conf). This has been corrected. </item> <item>
Arguments to <c>register_usm_users/2</c> were faulty
- documented. This has been corrected. </item> </list></p>
+ documented. This has been corrected. </item> </list>
<p>
Own Id: OTP-10434 Aux Id: kunagi-264 [175] </p>
</item>
@@ -1343,7 +1341,7 @@
</item>
<item>
<p>
- Update common test modules to handle unicode <list>
+ Update common test modules to handle unicode:</p> <list>
<item> Use UTF-8 encoding for all HTML files, except the
HTML version of the test suite generated with
erl2html2:convert, which will have the same encoding as
@@ -1354,7 +1352,7 @@
unicode:characters_to_list and
unicode:characters_to_binary for conversion between
binaries and strings instead of binary_to_list and
- list_to_binary. </item> </list></p>
+ list_to_binary. </item> </list>
<p>
Own Id: OTP-10783</p>
</item>
@@ -1395,7 +1393,6 @@
<p>
The following corrections/changes are done in the
cth_surefire hook:</p>
- <p>
<list> <item> Earlier there would always be a
'properties' element under the 'testsuites' element. This
would exist even if there were no 'property' element
@@ -1428,7 +1425,7 @@
</item> <item> A new option named 'url_base' is added for
this hook. If this option is used, a new attribute named
'url' will be added to the 'testcase' and 'testsuite'
- elements. </item> </list></p>
+ elements. </item> </list>
<p>
Own Id: OTP-10589</p>
</item>
diff --git a/lib/common_test/doc/src/run_test_chapter.xml b/lib/common_test/doc/src/run_test_chapter.xml
index d80453fc98..082a587c8d 100644
--- a/lib/common_test/doc/src/run_test_chapter.xml
+++ b/lib/common_test/doc/src/run_test_chapter.xml
@@ -60,15 +60,15 @@
<p>If compilation should fail for one or more suites, the compilation errors
are printed to tty and the operator is asked if the test run should proceed
without the missing suites, or be aborted. If the operator chooses to proceed,
- it is noted in the HTML log which tests have missing suites. If Common Test is
- unable to prompt the user after compilation failure (if Common Test doesn't
- control stdin), the test run will proceed automatically without the missing
- suites. This behaviour can however be modified with the
- <c><![CDATA[ct_run]]></c> flag <c><![CDATA[-abort_if_missing_suites]]></c>,
+ it is noted in the HTML log which tests have missing suites. Also, for each failed
+ compilation, the failed tests counter in the return value of
+ <c><![CDATA[ct:run_test/1]]></c> is incremented. If Common Test is unable to prompt
+ the user after compilation failure (if Common Test doesn't control stdin), the test
+ run will proceed automatically without the missing suites. In order to always
+ abort the test run (without operator interaction) if one or more suites fail
+ to compile, the <c><![CDATA[ct_run]]></c> flag <c><![CDATA[-abort_if_missing_suites]]></c>,
or the <c><![CDATA[ct:run_test/1]]></c> option
- <c><![CDATA[{abort_if_missing_suites,TrueOrFalse}]]></c>. If
- <c><![CDATA[abort_if_missing_suites]]></c> is set (to true), the test run
- will stop immediately if some suites fail to compile.</p>
+ <c><![CDATA[{abort_if_missing_suites,true}]]></c> should be set.</p>
<p>Any help module (i.e. regular Erlang module with name not ending with
"_SUITE") that resides in the same test object directory as a suite
diff --git a/lib/common_test/src/ct_config.erl b/lib/common_test/src/ct_config.erl
index 251204aa75..33efe7a14a 100644
--- a/lib/common_test/src/ct_config.erl
+++ b/lib/common_test/src/ct_config.erl
@@ -694,11 +694,10 @@ make_crypto_key(String) ->
{[K1,K2,K3],IVec}.
random_bytes(N) ->
- random:seed(os:timestamp()),
random_bytes_1(N, []).
random_bytes_1(0, Acc) -> Acc;
-random_bytes_1(N, Acc) -> random_bytes_1(N-1, [random:uniform(255)|Acc]).
+random_bytes_1(N, Acc) -> random_bytes_1(N-1, [rand:uniform(255)|Acc]).
check_callback_load(Callback) ->
case code:is_loaded(Callback) of
diff --git a/lib/common_test/src/ct_conn_log_h.erl b/lib/common_test/src/ct_conn_log_h.erl
index 2dd4fdac05..f7615fdc14 100644
--- a/lib/common_test/src/ct_conn_log_h.erl
+++ b/lib/common_test/src/ct_conn_log_h.erl
@@ -104,18 +104,31 @@ terminate(_,#state{logs=Logs}) ->
%%%-----------------------------------------------------------------
%%% Writing reports
write_report(_Time,#conn_log{header=false,module=ConnMod}=Info,Data,GL,State) ->
- {LogType,Fd} = get_log(Info,GL,State),
- io:format(Fd,"~n~ts",[format_data(ConnMod,LogType,Data)]);
+ case get_log(Info,GL,State) of
+ {silent,_} ->
+ ok;
+ {LogType,Fd} ->
+ io:format(Fd,"~n~ts",[format_data(ConnMod,LogType,Data)])
+ end;
write_report(Time,#conn_log{module=ConnMod}=Info,Data,GL,State) ->
- {LogType,Fd} = get_log(Info,GL,State),
- io:format(Fd,"~n~ts~ts~ts",[format_head(ConnMod,LogType,Time),
- format_title(LogType,Info),
- format_data(ConnMod,LogType,Data)]).
+ case get_log(Info,GL,State) of
+ {silent,_} ->
+ ok;
+ {LogType,Fd} ->
+ case format_data(ConnMod,LogType,Data) of
+ [] ->
+ ok;
+ FormattedData ->
+ io:format(Fd,"~n~ts~ts~ts",[format_head(ConnMod,LogType,Time),
+ format_title(LogType,Info),
+ FormattedData])
+ end
+ end.
write_error(Time,#conn_log{module=ConnMod}=Info,Report,GL,State) ->
case get_log(Info,GL,State) of
- {html,_} ->
+ {LogType,_} when LogType==html; LogType==silent ->
%% The error will anyway be written in the html log by the
%% sasl error handler, so don't write it again.
ok;
diff --git a/lib/common_test/src/ct_netconfc.erl b/lib/common_test/src/ct_netconfc.erl
index 0de7bf03af..6e3d1ab1d8 100644
--- a/lib/common_test/src/ct_netconfc.erl
+++ b/lib/common_test/src/ct_netconfc.erl
@@ -1272,6 +1272,14 @@ set_request_timer(T) ->
{ok,TRef} = timer:send_after(T,{Ref,timeout}),
{Ref,TRef}.
+%%%-----------------------------------------------------------------
+cancel_request_timer(undefined,undefined) ->
+ ok;
+cancel_request_timer(Ref,TRef) ->
+ _ = timer:cancel(TRef),
+ receive {Ref,timeout} -> ok
+ after 0 -> ok
+ end.
%%%-----------------------------------------------------------------
client_hello(Options) when is_list(Options) ->
@@ -1366,11 +1374,18 @@ to_xml_doc(Simple) ->
%%% Parse and handle received XML data
handle_data(NewData,#state{connection=Connection,buff=Buff0} = State0) ->
log(Connection,recv,NewData),
- Data = append_wo_initial_nl(Buff0,NewData),
- case binary:split(Data,[?END_TAG],[]) of
+ {Start,AddSz} =
+ case byte_size(Buff0) of
+ BSz when BSz<5 -> {0,BSz};
+ BSz -> {BSz-5,5}
+ end,
+ Length = byte_size(NewData) + AddSz,
+ Data = <<Buff0/binary, NewData/binary>>,
+ case binary:split(Data,?END_TAG,[{scope,{Start,Length}}]) of
[_NoEndTagFound] ->
{noreply, State0#state{buff=Data}};
- [FirstMsg,Buff1] ->
+ [FirstMsg0,Buff1] ->
+ FirstMsg = remove_initial_nl(FirstMsg0),
SaxArgs = [{event_fun,fun sax_event/3}, {event_state,[]}],
case xmerl_sax_parser:stream(FirstMsg, SaxArgs) of
{ok, Simple, _Thrash} ->
@@ -1392,11 +1407,10 @@ handle_data(NewData,#state{connection=Connection,buff=Buff0} = State0) ->
%% xml does not accept a leading nl and some netconf server add a nl after
%% each ?END_TAG, ignore them
-append_wo_initial_nl(<<>>,NewData) -> NewData;
-append_wo_initial_nl(<<"\n", Data/binary>>, NewData) ->
- append_wo_initial_nl(Data, NewData);
-append_wo_initial_nl(Data, NewData) ->
- <<Data/binary, NewData/binary>>.
+remove_initial_nl(<<"\n", Data/binary>>) ->
+ remove_initial_nl(Data);
+remove_initial_nl(Data) ->
+ Data.
handle_error(Reason, State) ->
Pending1 = case State#state.pending of
@@ -1404,9 +1418,9 @@ handle_error(Reason, State) ->
Pending ->
%% Assuming the first request gets the
%% first answer
- P=#pending{tref=TRef,caller=Caller} =
+ P=#pending{tref=TRef,ref=Ref,caller=Caller} =
lists:last(Pending),
- _ = timer:cancel(TRef),
+ cancel_request_timer(Ref,TRef),
Reason1 = {failed_to_parse_received_data,Reason},
ct_gen_conn:return(Caller,{error,Reason1}),
lists:delete(P,Pending)
@@ -1492,8 +1506,8 @@ decode({Tag,Attrs,_}=E, #state{connection=Connection,pending=Pending}=State) ->
{error,Reason} ->
{noreply,State#state{hello_status = {error,Reason}}}
end;
- #pending{tref=TRef,caller=Caller} ->
- _ = timer:cancel(TRef),
+ #pending{tref=TRef,ref=Ref,caller=Caller} ->
+ cancel_request_timer(Ref,TRef),
case decode_hello(E) of
{ok,SessionId,Capabilities} ->
ct_gen_conn:return(Caller,ok),
@@ -1519,9 +1533,8 @@ decode({Tag,Attrs,_}=E, #state{connection=Connection,pending=Pending}=State) ->
%% there is just one pending that matches (i.e. has
%% undefined msg_id and op)
case [P || P = #pending{msg_id=undefined,op=undefined} <- Pending] of
- [#pending{tref=TRef,
- caller=Caller}] ->
- _ = timer:cancel(TRef),
+ [#pending{tref=TRef,ref=Ref,caller=Caller}] ->
+ cancel_request_timer(Ref,TRef),
ct_gen_conn:return(Caller,E),
{noreply,State#state{pending=[]}};
_ ->
@@ -1542,8 +1555,8 @@ get_msg_id(Attrs) ->
decode_rpc_reply(MsgId,{_,Attrs,Content0}=E,#state{pending=Pending} = State) ->
case lists:keytake(MsgId,#pending.msg_id,Pending) of
- {value, #pending{tref=TRef,op=Op,caller=Caller}, Pending1} ->
- _ = timer:cancel(TRef),
+ {value, #pending{tref=TRef,ref=Ref,op=Op,caller=Caller}, Pending1} ->
+ cancel_request_timer(Ref,TRef),
Content = forward_xmlns_attr(Attrs,Content0),
{CallerReply,{ServerReply,State2}} =
do_decode_rpc_reply(Op,Content,State#state{pending=Pending1}),
@@ -1555,10 +1568,11 @@ decode_rpc_reply(MsgId,{_,Attrs,Content0}=E,#state{pending=Pending} = State) ->
%% pending that matches (i.e. has undefined msg_id and op)
case [P || P = #pending{msg_id=undefined,op=undefined} <- Pending] of
[#pending{tref=TRef,
+ ref=Ref,
msg_id=undefined,
op=undefined,
caller=Caller}] ->
- _ = timer:cancel(TRef),
+ cancel_request_timer(Ref,TRef),
ct_gen_conn:return(Caller,E),
{noreply,State#state{pending=[]}};
_ ->
@@ -1762,9 +1776,14 @@ format_data(How,Data) ->
do_format_data(raw,Data) ->
io_lib:format("~n~ts~n",[hide_password(Data)]);
do_format_data(pretty,Data) ->
- io_lib:format("~n~ts~n",[indent(Data)]);
+ maybe_io_lib_format(indent(Data));
do_format_data(html,Data) ->
- io_lib:format("~n~ts~n",[html_format(Data)]).
+ maybe_io_lib_format(html_format(Data)).
+
+maybe_io_lib_format(<<>>) ->
+ [];
+maybe_io_lib_format(String) ->
+ io_lib:format("~n~ts~n",[String]).
%%%-----------------------------------------------------------------
%%% Hide password elements from XML data
@@ -1803,13 +1822,21 @@ indent1("<?"++Rest1,Indent1) ->
Line++indent1(Rest2,Indent2);
indent1("</"++Rest1,Indent1) ->
%% Stop tag
- {Line,Rest2,Indent2} = indent_line1(Rest1,Indent1,[$/,$<]),
- "\n"++Line++indent1(Rest2,Indent2);
+ case indent_line1(Rest1,Indent1,[$/,$<]) of
+ {[],[],_} ->
+ [];
+ {Line,Rest2,Indent2} ->
+ "\n"++Line++indent1(Rest2,Indent2)
+ end;
indent1("<"++Rest1,Indent1) ->
%% Start- or empty tag
put(tag,get_tag(Rest1)),
- {Line,Rest2,Indent2} = indent_line(Rest1,Indent1,[$<]),
- "\n"++Line++indent1(Rest2,Indent2);
+ case indent_line(Rest1,Indent1,[$<]) of
+ {[],[],_} ->
+ [];
+ {Line,Rest2,Indent2} ->
+ "\n"++Line++indent1(Rest2,Indent2)
+ end;
indent1([H|T],Indent) ->
[H|indent1(T,Indent)];
indent1([],_Indent) ->
diff --git a/lib/common_test/src/ct_run.erl b/lib/common_test/src/ct_run.erl
index ae91601f67..0b646ffd07 100644
--- a/lib/common_test/src/ct_run.erl
+++ b/lib/common_test/src/ct_run.erl
@@ -1771,7 +1771,18 @@ compile_and_run(Tests, Skip, Opts, Args) ->
{Tests1,Skip1} ->
ReleaseSh = proplists:get_value(release_shell, Args),
ct_util:set_testdata({release_shell,ReleaseSh}),
- possibly_spawn(ReleaseSh == true, Tests1, Skip1, Opts)
+ TestResult =
+ possibly_spawn(ReleaseSh == true, Tests1, Skip1, Opts),
+ case TestResult of
+ {Ok,Errors,Skipped} ->
+ NoOfMakeErrors =
+ lists:foldl(fun({_,BadMods}, X) ->
+ X + length(BadMods)
+ end, 0, SuiteMakeErrors),
+ {Ok,Errors+NoOfMakeErrors,Skipped};
+ ErrorResult ->
+ ErrorResult
+ end
catch
_:BadFormat ->
{error,BadFormat}
@@ -2073,7 +2084,9 @@ final_skip([], Final) ->
continue([], _) ->
true;
-continue(_MakeErrors, AbortIfMissingSuites) ->
+continue(_MakeErrors, true) ->
+ false;
+continue(_MakeErrors, _AbortIfMissingSuites) ->
io:nl(),
OldGl = group_leader(),
case set_group_leader_same_as_shell() of
@@ -2101,11 +2114,10 @@ continue(_MakeErrors, AbortIfMissingSuites) ->
true
end;
false -> % no shell process to use
- not AbortIfMissingSuites
+ true
end.
set_group_leader_same_as_shell() ->
- %%! Locate the shell process... UGLY!!!
GS2or3 = fun(P) ->
case process_info(P,initial_call) of
{initial_call,{group,server,X}} when X == 2 ; X == 3 ->
diff --git a/lib/common_test/src/ct_slave.erl b/lib/common_test/src/ct_slave.erl
index 32a1ff4dbc..0cd83b9f04 100644
--- a/lib/common_test/src/ct_slave.erl
+++ b/lib/common_test/src/ct_slave.erl
@@ -1,7 +1,7 @@
%%--------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2015. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -134,7 +134,7 @@ start(Host, Node) ->
%%% executed after startup of the node. Note that all used modules should be
%%% present in the code path on the <code>Host</code>.</p>
%%%
-%%% <p>The timeouts are applied as follows:
+%%% <p>The timeouts are applied as follows:</p>
%%% <list>
%%% <item>
%%% <code>BootTimeout</code> - time to start the Erlang node, in seconds.
@@ -154,7 +154,7 @@ start(Host, Node) ->
%%% If this timeout occurs, the result
%%% <code>{error, startup_timeout, NodeName}</code> is returned.
%%% </item>
-%%% </list></p>
+%%% </list>
%%%
%%% <p>Option <code>monitor_master</code> specifies, if the slave node should be
%%% stopped in case of master node stop. Defaults to false.</p>
@@ -170,7 +170,7 @@ start(Host, Node) ->
%%% <p>Option <code>env</code> specifies a list of environment variables
%%% that will extended the environment.</p>
%%%
-%%% <p>Special return values are:
+%%% <p>Special return values are:</p>
%%% <list>
%%% <item><code>{error, already_started, NodeName}</code> - if the node with
%%% the given name is already started on a given host;</item>
@@ -179,7 +179,7 @@ start(Host, Node) ->
%%% <item><code>{error, not_alive, NodeName}</code> - if node on which the
%%% <code>ct_slave:start/3</code> is called, is not alive. Note that
%%% <code>NodeName</code> is the name of current node in this case.</item>
-%%% </list></p>
+%%% </list>
%%%
start(Host, Node, Opts) ->
ENode = enodename(Host, Node),
diff --git a/lib/common_test/src/ct_snmp.erl b/lib/common_test/src/ct_snmp.erl
index 95098bdaca..bb0167eb22 100644
--- a/lib/common_test/src/ct_snmp.erl
+++ b/lib/common_test/src/ct_snmp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2015. All 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 @@
%%% @doc Common Test user interface module for the OTP snmp application
%%%
-%%% The purpose of this module is to make snmp configuration easier for
+%%% <p>The purpose of this module is to make snmp configuration easier for
%%% the test case writer. Many test cases can use default values for common
%%% operations and then no snmp configuration files need to be supplied. When
%%% it is necessary to change particular configuration parameters, a subset
@@ -31,7 +31,7 @@
%%% To simplify the test suite, Common Test keeps track
%%% of some of the snmp manager information. This way the test suite doesn't
%%% have to handle as many input parameters as it would if it had to interface the
-%%% OTP snmp manager directly.
+%%% OTP snmp manager directly.</p>
%%%
%%% <p> The following snmp manager and agent parameters are configurable: </p>
%%%
@@ -326,9 +326,9 @@ set_info(Config) ->
%%% @doc Register the manager entity (=user) responsible for specific agent(s).
%%% Corresponds to making an entry in users.conf.
%%%
-%%% This function will try to register the given users, without
+%%% <p>This function will try to register the given users, without
%%% checking if any of them already exist. In order to change an
-%%% already registered user, the user must first be unregistered.
+%%% already registered user, the user must first be unregistered.</p>
register_users(MgrAgentConfName, Users) ->
case setup_users(Users) of
ok ->
@@ -351,10 +351,10 @@ register_users(MgrAgentConfName, Users) ->
%%% @doc Explicitly instruct the manager to handle this agent.
%%% Corresponds to making an entry in agents.conf
%%%
-%%% This function will try to register the given managed agents,
+%%% <p>This function will try to register the given managed agents,
%%% without checking if any of them already exist. In order to change
%%% an already registered managed agent, the agent must first be
-%%% unregistered.
+%%% unregistered.</p>
register_agents(MgrAgentConfName, ManagedAgents) ->
case setup_managed_agents(MgrAgentConfName,ManagedAgents) of
ok ->
@@ -378,9 +378,9 @@ register_agents(MgrAgentConfName, ManagedAgents) ->
%%% @doc Explicitly instruct the manager to handle this USM user.
%%% Corresponds to making an entry in usm.conf
%%%
-%%% This function will try to register the given users, without
+%%% <p>This function will try to register the given users, without
%%% checking if any of them already exist. In order to change an
-%%% already registered user, the user must first be unregistered.
+%%% already registered user, the user must first be unregistered.</p>
register_usm_users(MgrAgentConfName, UsmUsers) ->
EngineID = ct:get_config({MgrAgentConfName, engine_id}, ?ENGINE_ID),
case setup_usm_users(UsmUsers, EngineID) of
diff --git a/lib/common_test/src/ct_telnet.erl b/lib/common_test/src/ct_telnet.erl
index e9487e94db..4d3fd2d094 100644
--- a/lib/common_test/src/ct_telnet.erl
+++ b/lib/common_test/src/ct_telnet.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2015. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -327,16 +327,16 @@ cmd(Connection,Cmd) ->
%%% Reason = term()
%%% @doc Send a command via telnet and wait for prompt.
%%%
-%%% This function will by default add a newline to the end of the
+%%% <p>This function will by default add a newline to the end of the
%%% given command. If this is not desired, the option
%%% `{newline,false}' can be used. This is necessary, for example,
%%% when sending telnet command sequences (prefixed with the
-%%% Interprete As Command, IAC, character).
+%%% Interprete As Command, IAC, character).</p>
%%%
-%%% The option `timeout' specifies how long the client shall wait for
+%%% <p>The option `timeout' specifies how long the client shall wait for
%%% prompt. If the time expires, the function returns
%%% `{error,timeout}'. See the module description for information
-%%% about the default value for the command timeout.
+%%% about the default value for the command timeout.</p>
cmd(Connection,Cmd,Opts) when is_list(Opts) ->
case check_cmd_opts(Opts) of
ok ->
@@ -378,7 +378,7 @@ cmdf(Connection,CmdFormat,Args) ->
%%% @doc Send a telnet command and wait for prompt
%%% (uses a format string and list of arguments to build the command).
%%%
-%%% See {@link cmd/3} further description.
+%%% <p>See {@link cmd/3} further description.</p>
cmdf(Connection,CmdFormat,Args,Opts) when is_list(Args) ->
Cmd = lists:flatten(io_lib:format(CmdFormat,Args)),
cmd(Connection,Cmd,Opts).
diff --git a/lib/common_test/test/ct_master_SUITE.erl b/lib/common_test/test/ct_master_SUITE.erl
index 15b49c67c0..55837352e2 100644
--- a/lib/common_test/test/ct_master_SUITE.erl
+++ b/lib/common_test/test/ct_master_SUITE.erl
@@ -135,7 +135,7 @@ make_spec(DataDir, FileName, NodeNames, Suites, Config) ->
C = lists:map(
fun(NodeName) ->
- Rnd = random:uniform(2),
+ Rnd = rand:uniform(2),
if Rnd == 1->
{config,NodeName,filename:join(DataDir,
"master/config.txt")};
diff --git a/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl b/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl
index 64ebfbc463..ea49e36608 100644
--- a/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl
+++ b/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl
@@ -36,7 +36,8 @@
-compile(export_all).
suite() ->
- [{ct_hooks, [{cth_conn_log,
+ [{timetrap,?default_timeout},
+ {ct_hooks, [{cth_conn_log,
[{ct_netconfc,[{log_type,html}, %will be overwritten by config
{hosts,[my_named_connection,netconf1]}]
}]
@@ -72,7 +73,9 @@ all() ->
invalid_opt,
timeout_close_session,
get,
+ get_a_lot,
timeout_get,
+ flush_timeout_get,
get_xpath,
get_config,
get_config_xpath,
@@ -112,12 +115,9 @@ end_per_group(_GroupName, Config) ->
init_per_testcase(_Case, Config) ->
ets:delete_all_objects(ns_tab),
- Dog = test_server:timetrap(?default_timeout),
- [{watchdog, Dog}|Config].
+ Config.
-end_per_testcase(_Case, Config) ->
- Dog=?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
+end_per_testcase(_Case, _Config) ->
ok.
init_per_suite(Config) ->
@@ -351,6 +351,19 @@ get(Config) ->
?ok = ct_netconfc:close_session(Client),
ok.
+get_a_lot(Config) ->
+ DataDir = ?config(data_dir,Config),
+ {ok,Client} = open_success(DataDir),
+ Descr = lists:append(lists:duplicate(100,"Description of myserver! ")),
+ Server = {server,[{xmlns,"myns"}],[{name,[],["myserver"]},
+ {description,[],[Descr]}]},
+ Data = lists:duplicate(100,Server),
+ ?NS:expect_reply('get',{fragmented,{data,Data}}),
+ {ok,Data} = ct_netconfc:get(Client,{server,[{xmlns,"myns"}],[]}),
+ ?NS:expect_do_reply('close-session',close,ok),
+ ?ok = ct_netconfc:close_session(Client),
+ ok.
+
timeout_get(Config) ->
DataDir = ?config(data_dir,Config),
{ok,Client} = open_success(DataDir),
@@ -360,6 +373,28 @@ timeout_get(Config) ->
?ok = ct_netconfc:close_session(Client),
ok.
+%% Test OTP-13008 "ct_netconfc crash when receiving unknown timeout"
+%% If the timer expires "at the same time" as the rpc reply is
+%% received, the timeout message might already be sent when the timer
+%% is cancelled. This test checks that the timeout message is flushed
+%% from the message queue. If it isn't, the client crashes and the
+%% session can not be closed afterwards.
+%% Note that we can only hope that the test case triggers the problem
+%% every now and then, as it is very timing dependent...
+flush_timeout_get(Config) ->
+ DataDir = ?config(data_dir,Config),
+ {ok,Client} = open_success(DataDir),
+ Data = [{server,[{xmlns,"myns"}],[{name,[],["myserver"]}]}],
+ ?NS:expect_reply('get',{data,Data}),
+ timer:sleep(1000),
+ case ct_netconfc:get(Client,{server,[{xmlns,"myns"}],[]},1) of
+ {error,timeout} -> ok; % problem not triggered
+ {ok,Data} -> ok % problem possibly triggered
+ end,
+ ?NS:expect_do_reply('close-session',close,ok),
+ ?ok = ct_netconfc:close_session(Client),
+ ok.
+
get_xpath(Config) ->
DataDir = ?config(data_dir,Config),
{ok,Client} = open_success(DataDir),
diff --git a/lib/common_test/test/ct_netconfc_SUITE_data/ns.erl b/lib/common_test/test/ct_netconfc_SUITE_data/ns.erl
index 8c30383343..07893faabc 100644
--- a/lib/common_test/test/ct_netconfc_SUITE_data/ns.erl
+++ b/lib/common_test/test/ct_netconfc_SUITE_data/ns.erl
@@ -277,6 +277,18 @@ hupp_kill(State = #session{connection = ConnRef}) ->
send({CM,Ch},Data) ->
ssh_connection:send(CM, Ch, Data).
+%%% Split into many small parts and send to client
+send_frag({CM,Ch},Data) ->
+ Sz = rand:uniform(2000),
+ case Data of
+ <<Chunk:Sz/binary,Rest/binary>> ->
+ ssh_connection:send(CM, Ch, Chunk),
+ send_frag({CM,Ch},Rest);
+ Chunk ->
+ ssh_connection:send(CM, Ch, Chunk)
+ end.
+
+
%%% Kill ssh connection
kill({CM,_Ch}) ->
ssh:close(CM).
@@ -294,7 +306,7 @@ table_trans(Fun,Args) ->
receive
{table_trans_done,Result} ->
Result
- after 5000 ->
+ after 20000 ->
exit(table_trans_timeout)
end
end.
@@ -424,6 +436,9 @@ do(_, undefined) ->
reply(_,undefined) ->
?dbg("no reply~n",[]),
ok;
+reply(ConnRef,{fragmented,Reply}) ->
+ ?dbg("Reply fragmented: ~p~n",[Reply]),
+ send_frag(ConnRef,make_msg(Reply));
reply(ConnRef,Reply) ->
?dbg("Reply: ~p~n",[Reply]),
send(ConnRef, make_msg(Reply)).
diff --git a/lib/common_test/test/ct_test_support.erl b/lib/common_test/test/ct_test_support.erl
index 248ec6c4df..4a47d345e9 100644
--- a/lib/common_test/test/ct_test_support.erl
+++ b/lib/common_test/test/ct_test_support.erl
@@ -414,14 +414,14 @@ ct_rpc({M,F,A}, Config) ->
%%%-----------------------------------------------------------------
%%% random_error/1
random_error(Config) when is_list(Config) ->
- random:seed(os:timestamp()),
+ rand:seed(exsplus),
Gen = fun(0,_) -> ok; (N,Fun) -> Fun(N-1, Fun) end,
- Gen(random:uniform(100), Gen),
+ Gen(rand:uniform(100), Gen),
ErrorTypes = ['BADMATCH','BADARG','CASE_CLAUSE','FUNCTION_CLAUSE',
'EXIT','THROW','UNDEF'],
- Type = lists:nth(random:uniform(length(ErrorTypes)), ErrorTypes),
- Where = case random:uniform(2) of
+ Type = lists:nth(rand:uniform(length(ErrorTypes)), ErrorTypes),
+ Where = case rand:uniform(2) of
1 ->
io:format("ct_test_support *returning* error of type ~w",
[Type]),
diff --git a/lib/compiler/doc/src/notes.xml b/lib/compiler/doc/src/notes.xml
index bd85f22462..daf3bd3af9 100644
--- a/lib/compiler/doc/src/notes.xml
+++ b/lib/compiler/doc/src/notes.xml
@@ -458,22 +458,28 @@
<p>
EEP43: New data type - Maps</p>
<p>
- With Maps you may for instance: <taglist> <item><c>M0 =
- #{ a =&gt; 1, b =&gt; 2}, % create
- associations</c></item> <item><c>M1 = M0#{ a := 10 }, %
- update values</c></item> <item><c>M2 = M1#{ "hi" =&gt;
- "hello"}, % add new associations</c></item> <item><c>#{
- "hi" := V1, a := V2, b := V3} = M2. % match keys with
- values</c></item> </taglist></p>
+ With Maps you may for instance:</p>
+ <taglist>
+ <tag/> <item><c>M0 = #{ a =&gt; 1, b =&gt; 2}, % create
+ associations</c></item>
+ <tag/><item><c>M1 = M0#{ a := 10 }, % update values</c></item>
+ <tag/><item><c>M2 = M1#{ "hi" =&gt;
+ "hello"}, % add new associations</c></item>
+ <tag/><item><c>#{ "hi" := V1, a := V2, b := V3} = M2.
+ % match keys with values</c></item>
+ </taglist>
<p>
For information on how to use Maps please see Map Expressions in the
<seealso marker="doc/reference_manual:expressions#map_expressions">
Reference Manual</seealso>.</p>
<p>
The current implementation is without the following
- features: <taglist> <item>No variable keys</item>
- <item>No single value access</item> <item>No map
- comprehensions</item> </taglist></p>
+ features:</p>
+ <taglist>
+ <tag/><item>No variable keys</item>
+ <tag/><item>No single value access</item>
+ <tag/><item>No map comprehensions</item>
+ </taglist>
<p>
Note that Maps is <em>experimental</em> during OTP 17.0.</p>
<p>
diff --git a/lib/compiler/src/beam_asm.erl b/lib/compiler/src/beam_asm.erl
index a3201b0f4a..95be471de3 100644
--- a/lib/compiler/src/beam_asm.erl
+++ b/lib/compiler/src/beam_asm.erl
@@ -30,11 +30,12 @@
module(Code, Abst, SourceFile, Opts) ->
{ok,assemble(Code, Abst, SourceFile, Opts)}.
-assemble({Mod,Exp,Attr0,Asm0,NumLabels}, Abst, SourceFile, Opts) ->
+assemble({Mod,Exp0,Attr0,Asm0,NumLabels}, Abst, SourceFile, Opts) ->
{1,Dict0} = beam_dict:atom(Mod, beam_dict:new()),
{0,Dict1} = beam_dict:fname(atom_to_list(Mod) ++ ".erl", Dict0),
NumFuncs = length(Asm0),
{Asm,Attr} = on_load(Asm0, Attr0),
+ Exp = cerl_sets:from_list(Exp0),
{Code,Dict2} = assemble_1(Asm, Exp, Dict1, []),
build_file(Code, Attr, Dict2, NumLabels, NumFuncs, Abst, SourceFile, Opts).
@@ -61,7 +62,7 @@ insert_on_load_instruction(Is0, Entry) ->
Bef ++ [El,on_load|Is].
assemble_1([{function,Name,Arity,Entry,Asm}|T], Exp, Dict0, Acc) ->
- Dict1 = case member({Name,Arity}, Exp) of
+ Dict1 = case cerl_sets:is_element({Name,Arity}, Exp) of
true ->
beam_dict:export(Name, Arity, Entry, Dict0);
false ->
diff --git a/lib/compiler/src/beam_dict.erl b/lib/compiler/src/beam_dict.erl
index 2b5f8c1b7f..654fb47dbd 100644
--- a/lib/compiler/src/beam_dict.erl
+++ b/lib/compiler/src/beam_dict.erl
@@ -44,7 +44,7 @@
locals = [] :: [{label(), arity(), label()}],
imports = gb_trees:empty() :: import_tab(),
strings = <<>> :: binary(), %String pool
- lambdas = [], %[{...}]
+ lambdas = {0,[]}, %[{...}]
literals = dict:new() :: literal_tab(),
fnames = #{} :: fname_tab(),
lines = #{} :: line_tab(),
@@ -145,15 +145,14 @@ string(Str, Dict) when is_list(Str) ->
-spec lambda(label(), non_neg_integer(), bdict()) ->
{non_neg_integer(), bdict()}.
-lambda(Lbl, NumFree, #asm{lambdas=Lambdas0}=Dict) ->
- OldIndex = length(Lambdas0),
+lambda(Lbl, NumFree, #asm{lambdas={OldIndex,Lambdas0}}=Dict) ->
%% Set Index the same as OldIndex.
Index = OldIndex,
%% Initialize OldUniq to 0. It will be set to an unique value
%% based on the MD5 checksum of the BEAM code for the module.
OldUniq = 0,
Lambdas = [{Lbl,{OldIndex,Lbl,Index,NumFree,OldUniq}}|Lambdas0],
- {OldIndex,Dict#asm{lambdas=Lambdas}}.
+ {OldIndex,Dict#asm{lambdas={OldIndex+1,Lambdas}}}.
%% Returns the index for a literal (adding it to the literal table if necessary).
%% literal(Literal, Dict) -> {Index,Dict'}
@@ -236,13 +235,13 @@ string_table(#asm{strings=Strings,string_offset=Size}) ->
-spec lambda_table(bdict()) -> {non_neg_integer(), [<<_:192>>]}.
-lambda_table(#asm{locals=Loc0,lambdas=Lambdas0}) ->
+lambda_table(#asm{locals=Loc0,lambdas={NumLambdas,Lambdas0}}) ->
Lambdas1 = sofs:relation(Lambdas0),
Loc = sofs:relation([{Lbl,{F,A}} || {F,A,Lbl} <- Loc0]),
Lambdas2 = sofs:relative_product1(Lambdas1, Loc),
Lambdas = [<<F:32,A:32,Lbl:32,Index:32,NumFree:32,OldUniq:32>> ||
{{_,Lbl,Index,NumFree,OldUniq},{F,A}} <- sofs:to_external(Lambdas2)],
- {length(Lambdas),Lambdas}.
+ {NumLambdas,Lambdas}.
%% Returns the literal table.
%% literal_table(Dict) -> {NumLiterals, [<<TermSize>>,TermInExternalFormat]}
diff --git a/lib/compiler/src/beam_validator.erl b/lib/compiler/src/beam_validator.erl
index cdace42a68..fd38fc0095 100644
--- a/lib/compiler/src/beam_validator.erl
+++ b/lib/compiler/src/beam_validator.erl
@@ -31,13 +31,6 @@
-import(lists, [reverse/1,foldl/3,foreach/2,dropwhile/2]).
-%%-define(DEBUG, 1).
--ifdef(DEBUG).
--define(DBG_FORMAT(F, D), (io:format((F), (D)))).
--else.
--define(DBG_FORMAT(F, D), ok).
--endif.
-
%% To be called by the compiler.
module({Mod,Exp,Attr,Fs,Lc}=Code, _Opts)
when is_atom(Mod), is_list(Exp), is_list(Attr), is_integer(Lc) ->
@@ -168,29 +161,18 @@ validate_0(Module, [{function,Name,Ar,Entry,Code}|Fs], Ft) ->
% in the module (those that start with bs_start_match2).
}).
--ifdef(DEBUG).
-print_st(#st{x=Xs,y=Ys,numy=NumY,h=H,ct=Ct}) ->
- io:format(" #st{x=~p~n"
- " y=~p~n"
- " numy=~p,h=~p,ct=~w~n",
- [gb_trees:to_list(Xs),gb_trees:to_list(Ys),NumY,H,Ct]).
--endif.
-
validate_1(Is, Name, Arity, Entry, Ft) ->
validate_2(labels(Is), Name, Arity, Entry, Ft).
validate_2({Ls1,[{func_info,{atom,Mod},{atom,Name},Arity}=_F|Is]},
Name, Arity, Entry, Ft) ->
- lists:foreach(fun (_L) -> ?DBG_FORMAT(" ~p.~n", [{label,_L}]) end, Ls1),
- ?DBG_FORMAT(" ~p.~n", [_F]),
validate_3(labels(Is), Name, Arity, Entry, Mod, Ls1, Ft);
validate_2({Ls1,Is}, Name, Arity, _Entry, _Ft) ->
error({{'_',Name,Arity},{first(Is),length(Ls1),illegal_instruction}}).
validate_3({Ls2,Is}, Name, Arity, Entry, Mod, Ls1, Ft) ->
- lists:foreach(fun (_L) -> ?DBG_FORMAT(" ~p.~n", [{label,_L}]) end, Ls2),
Offset = 1 + length(Ls1) + 1 + length(Ls2),
- EntryOK = (Entry =:= undefined) orelse lists:member(Entry, Ls2),
+ EntryOK = lists:member(Entry, Ls2),
if
EntryOK ->
St = init_state(Arity),
@@ -258,7 +240,6 @@ valfun([], MFA, _Offset, #vst{branched=Targets0,labels=Labels0}=Vst) ->
error({MFA,Error})
end;
valfun([I|Is], MFA, Offset, Vst0) ->
- ?DBG_FORMAT(" ~p.\n", [I]),
valfun(Is, MFA, Offset+1,
try
Vst = val_dsetel(I, Vst0),
@@ -276,7 +257,6 @@ valfun_1({label,Lbl}, #vst{current=St0,branched=B,labels=Lbls}=Vst) ->
valfun_1(_I, #vst{current=none}=Vst) ->
%% Ignore instructions after erlang:error/1,2, which
%% the original R10B compiler thought would return.
- ?DBG_FORMAT("Ignoring ~p\n", [_I]),
Vst;
valfun_1({badmatch,Src}, Vst) ->
assert_term(Src, Vst),
@@ -1626,8 +1606,4 @@ min(A, B) when is_integer(A), is_integer(B) -> B.
gb_trees_from_list(L) -> gb_trees:from_orddict(lists:sort(L)).
--ifdef(DEBUG).
-error(Error) -> exit(Error).
--else.
error(Error) -> throw(Error).
--endif.
diff --git a/lib/compiler/src/cerl_trees.erl b/lib/compiler/src/cerl_trees.erl
index 2c9b72a30b..58bb18e34a 100644
--- a/lib/compiler/src/cerl_trees.erl
+++ b/lib/compiler/src/cerl_trees.erl
@@ -731,8 +731,8 @@ label(T, N, Env) ->
{ann_c_map(As, M, Ts), N3};
map_pair ->
{Op, N1} = label(map_pair_op(T), N, Env),
- {Val, N2} = label(map_pair_key(T), N1, Env),
- {Key, N3} = label(map_pair_val(T), N2, Env),
+ {Key, N2} = label(map_pair_key(T), N1, Env),
+ {Val, N3} = label(map_pair_val(T), N2, Env),
{As, N4} = label_ann(T, N3),
{ann_c_map_pair(As,Op,Key,Val), N4};
'let' ->
diff --git a/lib/compiler/src/compile.erl b/lib/compiler/src/compile.erl
index a2a23a2b90..b61c104b3c 100644
--- a/lib/compiler/src/compile.erl
+++ b/lib/compiler/src/compile.erl
@@ -1306,21 +1306,12 @@ generate_key(String) when is_list(String) ->
encrypt({des3_cbc=Type,Key,IVec,BlockSize}, Bin0) ->
Bin1 = case byte_size(Bin0) rem BlockSize of
0 -> Bin0;
- N -> list_to_binary([Bin0,random_bytes(BlockSize-N)])
+ N -> list_to_binary([Bin0,crypto:rand_bytes(BlockSize-N)])
end,
Bin = crypto:block_encrypt(Type, Key, IVec, Bin1),
TypeString = atom_to_list(Type),
list_to_binary([0,length(TypeString),TypeString,Bin]).
-random_bytes(N) ->
- _ = random:seed(erlang:time_offset(),
- erlang:monotonic_time(),
- erlang:unique_integer()),
- random_bytes_1(N, []).
-
-random_bytes_1(0, Acc) -> Acc;
-random_bytes_1(N, Acc) -> random_bytes_1(N-1, [random:uniform(255)|Acc]).
-
save_core_code(St) ->
{ok,St#compile{core_code=cerl:from_records(St#compile.code)}}.
diff --git a/lib/compiler/src/rec_env.erl b/lib/compiler/src/rec_env.erl
index 0e9e12d1ad..5a4a870769 100644
--- a/lib/compiler/src/rec_env.erl
+++ b/lib/compiler/src/rec_env.erl
@@ -598,7 +598,16 @@ start_range(Env) ->
%% (pseudo-)randomly distributed over the range.
generate(_N, Range) ->
- random:uniform(Range). % works well
+ %% We must use the same sequence of random variables to ensure
+ %% that two compilations of the same source code generates the
+ %% same BEAM code.
+ case rand:export_seed() of
+ undefined ->
+ rand:seed(exsplus, {1,42,2053});
+ _ ->
+ ok
+ end,
+ rand:uniform(Range). % works well
%% =====================================================================
diff --git a/lib/compiler/src/sys_core_dsetel.erl b/lib/compiler/src/sys_core_dsetel.erl
index ac32db10fe..c6cfdbae7e 100644
--- a/lib/compiler/src/sys_core_dsetel.erl
+++ b/lib/compiler/src/sys_core_dsetel.erl
@@ -72,7 +72,7 @@ module(M0, _Options) ->
{ok,M}.
visit_module(#c_module{defs=Ds0}=R) ->
- Env = dict:new(),
+ Env = #{},
Ds = visit_module_1(Ds0, Env, []),
R#c_module{defs=Ds}.
@@ -95,9 +95,11 @@ visit(Env, #c_var{name={_,_}}=R) ->
{R, Env};
visit(Env0, #c_var{name=X}=R) ->
%% There should not be any free variables. If there are,
- %% the next line will cause an exception.
- {ok, N} = dict:find(X, Env0),
- {R, dict:store(X, N+1, Env0)};
+ %% the case will fail with an exception.
+ case Env0 of
+ #{X:=N} ->
+ {R, Env0#{X:=N+1}}
+ end;
visit(Env, #c_literal{}=R) ->
{R, Env};
visit(Env0, #c_tuple{es=Es0}=R) ->
@@ -203,7 +205,7 @@ bind_vars(Vs, Env) ->
bind_vars(Vs, Env, []).
bind_vars([#c_var{name=X}|Vs], Env0, Xs)->
- bind_vars(Vs, dict:store(X, 0, Env0), [X|Xs]);
+ bind_vars(Vs, Env0#{X=>0}, [X|Xs]);
bind_vars([], Env,Xs) ->
{Xs, Env}.
@@ -217,7 +219,7 @@ visit_pats([], Env, Vs) ->
{Vs, Env}.
visit_pat(Env0, #c_var{name=V}, Vs) ->
- {[V|Vs], dict:store(V, 0, Env0)};
+ {[V|Vs], Env0#{V=>0}};
visit_pat(Env0, #c_tuple{es=Es}, Vs) ->
visit_pats(Es, Env0, Vs);
visit_pat(Env0, #c_map{es=Es}, Vs) ->
@@ -235,23 +237,25 @@ visit_pat(Env0, #c_bitstr{val=Val,size=Sz}, Vs0) ->
case Sz of
#c_var{name=V} ->
%% We don't tolerate free variables.
- {ok, N} = dict:find(V, Env0),
- {Vs0, dict:store(V, N+1, Env0)};
+ case Env0 of
+ #{V:=N} ->
+ {Vs0, Env0#{V:=N+1}}
+ end;
_ ->
visit_pat(Env0, Sz, Vs0)
end,
visit_pat(Env1, Val, Vs1);
visit_pat(Env0, #c_alias{pat=P,var=#c_var{name=V}}, Vs) ->
- visit_pat(dict:store(V, 0, Env0), P, [V|Vs]);
+ visit_pat(Env0#{V=>0}, P, [V|Vs]);
visit_pat(Env, #c_literal{}, Vs) ->
{Vs, Env}.
restore_vars([V|Vs], Env0, Env1) ->
- case dict:find(V, Env0) of
- {ok, N} ->
- restore_vars(Vs, Env0, dict:store(V, N, Env1));
- error ->
- restore_vars(Vs, Env0, dict:erase(V, Env1))
+ case Env0 of
+ #{V:=N} ->
+ restore_vars(Vs, Env0, Env1#{V=>N});
+ _ ->
+ restore_vars(Vs, Env0, maps:remove(V, Env1))
end;
restore_vars([], _, Env1) ->
Env1.
@@ -349,8 +353,8 @@ is_safe(#c_literal{}) -> true;
is_safe(_) -> false.
is_single_use(V, Env) ->
- case dict:find(V, Env) of
- {ok, 1} ->
+ case Env of
+ #{V:=1} ->
true;
_ ->
false
diff --git a/lib/compiler/src/sys_core_fold.erl b/lib/compiler/src/sys_core_fold.erl
index 0a16776bd4..43ce9a7172 100644
--- a/lib/compiler/src/sys_core_fold.erl
+++ b/lib/compiler/src/sys_core_fold.erl
@@ -3097,12 +3097,12 @@ bsm_ensure_no_partition_2([#c_var{name=V}|Ps], N, G, Vstate, S) ->
bsm_ensure_no_partition_2([_|Ps], N, G, _, S) ->
bsm_ensure_no_partition_2(Ps, N-1, G, bin_argument_order, S).
-bsm_ensure_no_partition_after([#c_clause{pats=Ps}|Cs], Pos) ->
+bsm_ensure_no_partition_after([#c_clause{pats=Ps}=C|Cs], Pos) ->
case nth(Pos, Ps) of
#c_var{} ->
bsm_ensure_no_partition_after(Cs, Pos);
- P ->
- bsm_problem(P, bin_partition)
+ _ ->
+ bsm_problem(C, bin_partition)
end;
bsm_ensure_no_partition_after([], _) -> ok.
diff --git a/lib/compiler/src/sys_pre_expand.erl b/lib/compiler/src/sys_pre_expand.erl
index d9cc4b530c..7ab4e1845c 100644
--- a/lib/compiler/src/sys_pre_expand.erl
+++ b/lib/compiler/src/sys_pre_expand.erl
@@ -29,30 +29,26 @@
%% Main entry point.
-export([module/2]).
--import(ordsets, [from_list/1,union/2]).
-import(lists, [member/2,foldl/3,foldr/3]).
--include("../include/erl_bits.hrl").
-
-type fa() :: {atom(), arity()}.
-record(expand, {module=[], %Module name
exports=[], %Exports
- imports=[], %Imports
attributes=[], %Attributes
callbacks=[], %Callbacks
optional_callbacks=[] :: [fa()], %Optional callbacks
- defined, %Defined functions (gb_set)
vcount=0, %Variable counter
func=[], %Current function
arity=[], %Arity for current function
- fcount=0 %Local fun count
+ fcount=0, %Local fun count
+ ctype %Call type map
}).
%% module(Forms, CompileOptions)
%% {ModuleName,Exports,TransformedForms,CompileOptions'}
-%% Expand the forms in one module. N.B.: the lists of predefined
-%% exports and imports are really ordsets!
+%% Expand the forms in one module.
+%%
%% CompileOptions is augmented with options from -compile attributes.
module(Fs0, Opts0) ->
@@ -65,19 +61,28 @@ module(Fs0, Opts0) ->
%% Set pre-defined exported functions.
PreExp = [{module_info,0},{module_info,1}],
+ %% Build the set of defined functions and the initial call
+ %% type map.
+ Defined = defined_functions(Fs, PreExp),
+ Ctype = maps:from_list([{K,local} || K <- Defined]),
+
%% Build initial expand record.
St0 = #expand{exports=PreExp,
- defined=PreExp
+ ctype=Ctype
},
+
%% Expand the functions.
- {Tfs,St1} = forms(Fs, define_functions(Fs, St0)),
+ {Tfs,St1} = forms(Fs, St0),
+
%% Get the correct list of exported functions.
Exports = case member(export_all, Opts) of
- true -> gb_sets:to_list(St1#expand.defined);
+ true -> Defined;
false -> St1#expand.exports
end,
+ St2 = St1#expand{exports=Exports,ctype=undefined},
+
%% Generate all functions from stored info.
- {Ats,St3} = module_attrs(St1#expand{exports = Exports}),
+ {Ats,St3} = module_attrs(St2),
{Mfs,St4} = module_predef_funcs(St3),
{St4#expand.module, St4#expand.exports, Ats ++ Tfs ++ Mfs,
Opts}.
@@ -85,14 +90,14 @@ module(Fs0, Opts0) ->
compiler_options(Forms) ->
lists:flatten([C || {attribute,_,compile,C} <- Forms]).
-%% define_function(Form, State) -> State.
+%% defined_function(Forms, Predef) -> Functions.
%% Add function to defined if form is a function.
-define_functions(Forms, #expand{defined=Predef}=St) ->
+defined_functions(Forms, Predef) ->
Fs = foldl(fun({function,_,N,A,_Cs}, Acc) -> [{N,A}|Acc];
(_, Acc) -> Acc
end, Predef, Forms),
- St#expand{defined=gb_sets:from_list(Fs)}.
+ ordsets:from_list(Fs).
module_attrs(#expand{attributes=Attributes}=St) ->
Attrs = [{attribute,Line,Name,Val} || {Name,Line,Val} <- Attributes],
@@ -113,23 +118,21 @@ is_fa_list([{FuncName, Arity}|L])
is_fa_list([]) -> true;
is_fa_list(_) -> false.
-module_predef_funcs(St) ->
- {Mpf1,St1}=module_predef_func_beh_info(St),
- {Mpf2,St2}=module_predef_funcs_mod_info(St1),
+module_predef_funcs(St0) ->
+ {Mpf1,St1} = module_predef_func_beh_info(St0),
+ Mpf2 = module_predef_funcs_mod_info(St1),
Mpf = [erl_parse:new_anno(F) || F <- Mpf1++Mpf2],
- {Mpf,St2}.
+ {Mpf,St1}.
module_predef_func_beh_info(#expand{callbacks=[]}=St) ->
{[], St};
module_predef_func_beh_info(#expand{callbacks=Callbacks,
optional_callbacks=OptionalCallbacks,
- defined=Defined,
exports=Exports}=St) ->
- PreDef=[{behaviour_info,1}],
- PreExp=PreDef,
+ PreDef0 = [{behaviour_info,1}],
+ PreDef = ordsets:from_list(PreDef0),
{[gen_beh_info(Callbacks, OptionalCallbacks)],
- St#expand{defined=gb_sets:union(gb_sets:from_list(PreDef), Defined),
- exports=union(from_list(PreExp), Exports)}}.
+ St#expand{exports=ordsets:union(PreDef, Exports)}}.
gen_beh_info(Callbacks, OptionalCallbacks) ->
List = make_list(Callbacks),
@@ -156,20 +159,16 @@ make_optional_list([{Name,Arity}|Rest]) ->
{integer,0,Arity}]},
make_optional_list(Rest)}.
-module_predef_funcs_mod_info(St) ->
- PreDef = [{module_info,0},{module_info,1}],
- PreExp = PreDef,
- {[{function,0,module_info,0,
- [{clause,0,[],[],
+module_predef_funcs_mod_info(#expand{module=Mod}) ->
+ ModAtom = {atom,0,Mod},
+ [{function,0,module_info,0,
+ [{clause,0,[],[],
[{call,0,{remote,0,{atom,0,erlang},{atom,0,get_module_info}},
- [{atom,0,St#expand.module}]}]}]},
- {function,0,module_info,1,
- [{clause,0,[{var,0,'X'}],[],
+ [ModAtom]}]}]},
+ {function,0,module_info,1,
+ [{clause,0,[{var,0,'X'}],[],
[{call,0,{remote,0,{atom,0,erlang},{atom,0,get_module_info}},
- [{atom,0,St#expand.module},{var,0,'X'}]}]}]}],
- St#expand{defined=gb_sets:union(gb_sets:from_list(PreDef),
- St#expand.defined),
- exports=union(from_list(PreExp), St#expand.exports)}}.
+ [ModAtom,{var,0,'X'}]}]}]}].
%% forms(Forms, State) ->
%% {TransformedForms,State'}
@@ -196,7 +195,8 @@ attribute(module, Module, _L, St) ->
true = is_atom(Module),
St#expand{module=Module};
attribute(export, Es, _L, St) ->
- St#expand{exports=union(from_list(Es), St#expand.exports)};
+ St#expand{exports=ordsets:union(ordsets:from_list(Es),
+ St#expand.exports)};
attribute(import, Is, _L, St) ->
import(Is, St);
attribute(compile, _C, _L, St) ->
@@ -231,8 +231,6 @@ head(As, St) -> pattern_list(As, St).
%% {TransformedPattern,State'}
%%
-pattern({var,_,'_'}=Var, St) -> %Ignore anonymous variable.
- {Var,St};
pattern({var,_,_}=Var, St) ->
{Var,St};
pattern({char,_,_}=Char, St) ->
@@ -385,19 +383,19 @@ expr({block,Line,Es0}, St0) ->
{Es,St1} = exprs(Es0, St0),
{{block,Line,Es},St1};
expr({'if',Line,Cs0}, St0) ->
- {Cs,St1} = icr_clauses(Cs0, St0),
+ {Cs,St1} = clauses(Cs0, St0),
{{'if',Line,Cs},St1};
expr({'case',Line,E0,Cs0}, St0) ->
{E,St1} = expr(E0, St0),
- {Cs,St2} = icr_clauses(Cs0, St1),
+ {Cs,St2} = clauses(Cs0, St1),
{{'case',Line,E,Cs},St2};
expr({'receive',Line,Cs0}, St0) ->
- {Cs,St1} = icr_clauses(Cs0, St0),
+ {Cs,St1} = clauses(Cs0, St0),
{{'receive',Line,Cs},St1};
expr({'receive',Line,Cs0,To0,ToEs0}, St0) ->
{To,St1} = expr(To0, St0),
{ToEs,St2} = exprs(ToEs0, St1),
- {Cs,St3} = icr_clauses(Cs0, St2),
+ {Cs,St3} = clauses(Cs0, St2),
{{'receive',Line,Cs,To,ToEs},St3};
expr({'fun',Line,Body}, St) ->
fun_tq(Line, Body, St);
@@ -406,21 +404,15 @@ expr({named_fun,Line,Name,Cs}, St) ->
expr({call,Line,{atom,La,N}=Atom,As0}, St0) ->
{As,St1} = expr_list(As0, St0),
Ar = length(As),
- case defined(N,Ar,St1) of
- true ->
+ Key = {N,Ar},
+ case St1#expand.ctype of
+ #{Key:=local} ->
{{call,Line,Atom,As},St1};
+ #{Key:={imported,Mod}} ->
+ {{call,Line,{remote,La,{atom,La,Mod},Atom},As},St1};
_ ->
- case imported(N, Ar, St1) of
- {yes,Mod} ->
- {{call,Line,{remote,La,{atom,La,Mod},Atom},As},St1};
- no ->
- case erl_internal:bif(N, Ar) of
- true ->
- {{call,Line,{remote,La,{atom,La,erlang},Atom},As},St1};
- false -> %% This should have been handled by erl_lint
- {{call,Line,Atom,As},St1}
- end
- end
+ true = erl_internal:bif(N, Ar),
+ {{call,Line,{remote,La,{atom,La,erlang},Atom},As},St1}
end;
expr({call,Line,{remote,Lr,M0,F},As0}, St0) ->
{[M1,F1|As1],St1} = expr_list([M0,F|As0], St0),
@@ -430,12 +422,11 @@ expr({call,Line,F,As0}, St0) ->
{{call,Line,Fun1,As1},St1};
expr({'try',Line,Es0,Scs0,Ccs0,As0}, St0) ->
{Es1,St1} = exprs(Es0, St0),
- {Scs1,St2} = icr_clauses(Scs0, St1),
- {Ccs1,St3} = icr_clauses(Ccs0, St2),
+ {Scs1,St2} = clauses(Scs0, St1),
+ {Ccs1,St3} = clauses(Ccs0, St2),
{As1,St4} = exprs(As0, St3),
{{'try',Line,Es1,Scs1,Ccs1,As1},St4};
expr({'catch',Line,E0}, St0) ->
- %% Catch exports no new variables.
{E,St1} = expr(E0, St0),
{{'catch',Line,E},St1};
expr({match,Line,P0,E0}, St0) ->
@@ -456,21 +447,6 @@ expr_list([E0|Es0], St0) ->
{[E|Es],St2};
expr_list([], St) -> {[],St}.
-%% icr_clauses([Clause], State) -> {[TransformedClause],State'}
-%% Be very careful here to return the variables that are really used
-%% and really new.
-
-icr_clauses([], St) -> {[],St};
-icr_clauses(Clauses, St) -> icr_clauses2(Clauses, St).
-
-icr_clauses2([{clause,Line,H0,G0,B0}|Cs0], St0) ->
- {H,St1} = head(H0, St0),
- {G,St2} = guard(G0, St1),
- {B,St3} = exprs(B0, St2),
- {Cs,St4} = icr_clauses2(Cs0, St3),
- {[{clause,Line,H,G,B}|Cs],St4};
-icr_clauses2([], St) -> {[],St}.
-
%% lc_tq(Line, Qualifiers, State) ->
%% {[TransQual],State'}
@@ -486,16 +462,9 @@ lc_tq(Line, [{b_generate,Lg,P0,G0}|Qs0], St0) ->
{Qs1,St3} = lc_tq(Line, Qs0, St2),
{[{b_generate,Lg,P1,G1}|Qs1],St3};
lc_tq(Line, [F0 | Qs0], St0) ->
- case erl_lint:is_guard_test(F0) of
- true ->
- {F1,St1} = guard_test(F0, St0),
- {Qs1,St2} = lc_tq(Line, Qs0, St1),
- {[F1|Qs1],St2};
- false ->
- {F1,St1} = expr(F0, St0),
- {Qs1,St2} = lc_tq(Line, Qs0, St1),
- {[F1 | Qs1],St2}
- end;
+ {F1,St1} = expr(F0, St0),
+ {Qs1,St2} = lc_tq(Line, Qs0, St1),
+ {[F1|Qs1],St2};
lc_tq(_Line, [], St0) ->
{[],St0}.
@@ -527,7 +496,7 @@ fun_tq(L, {function,M,F,A}, St) when is_atom(M), is_atom(F), is_integer(A) ->
fun_tq(Lf, {function,_,_,_}=ExtFun, St) ->
{{'fun',Lf,ExtFun},St};
fun_tq(Lf, {clauses,Cs0}, St0) ->
- {Cs1,St1} = fun_clauses(Cs0, St0),
+ {Cs1,St1} = clauses(Cs0, St0),
{Fname,St2} = new_fun_name(St1),
%% Set dummy values for Index and Uniq -- the real values will
%% be assigned by beam_asm.
@@ -535,18 +504,10 @@ fun_tq(Lf, {clauses,Cs0}, St0) ->
{{'fun',Lf,{clauses,Cs1},{Index,Uniq,Fname}},St2}.
fun_tq(Line, Cs0, St0, Name) ->
- {Cs1,St1} = fun_clauses(Cs0, St0),
+ {Cs1,St1} = clauses(Cs0, St0),
{Fname,St2} = new_fun_name(St1, Name),
{{named_fun,Line,Name,Cs1,{0,0,Fname}},St2}.
-fun_clauses([{clause,L,H0,G0,B0}|Cs0], St0) ->
- {H,St1} = head(H0, St0),
- {G,St2} = guard(G0, St1),
- {B,St3} = exprs(B0, St2),
- {Cs,St4} = fun_clauses(Cs0, St3),
- {[{clause,L,H,G,B}|Cs],St4};
-fun_clauses([], St) -> {[],St}.
-
%% new_fun_name(State) -> {FunName,State}.
new_fun_name(St) ->
@@ -571,7 +532,6 @@ pattern_element({bin_element,Line,Expr0,Size0,Type0}, {Es,St0}) ->
{[{bin_element,Line,Expr,Size,Type}|Es],St2}.
pat_bit_size(default, St) -> {default,St};
-pat_bit_size({atom,_La,all}=All, St) -> {All,St};
pat_bit_size({var,_Lv,_V}=Var, St) -> {Var,St};
pat_bit_size(Size, St) ->
Line = element(2, Size),
@@ -592,8 +552,7 @@ coerce_to_float({integer,L,I}=E, [float|_]) ->
try
{float,L,float(I)}
catch
- error:badarg -> E;
- error:badarith -> E
+ error:badarg -> E
end;
coerce_to_float(E, _) -> E.
@@ -647,25 +606,11 @@ string_to_conses(Line, Cs, Tail) ->
%% import(Line, Imports, State) ->
%% State'
-%% imported(Name, Arity, State) ->
-%% {yes,Module} | no
-%% Handle import declarations and test for imported functions. No need to
-%% check when building imports as code is correct.
+%% Handle import declarations.
-import({Mod,Fs}, St) ->
+import({Mod,Fs}, #expand{ctype=Ctype0}=St) ->
true = is_atom(Mod),
- Mfs = from_list(Fs),
- St#expand{imports=add_imports(Mod, Mfs, St#expand.imports)}.
-
-add_imports(Mod, [F|Fs], Is) ->
- add_imports(Mod, Fs, orddict:store(F, Mod, Is));
-add_imports(_, [], Is) -> Is.
-
-imported(F, A, St) ->
- case orddict:find({F,A}, St#expand.imports) of
- {ok,Mod} -> {yes,Mod};
- error -> no
- end.
-
-defined(F, A, St) ->
- gb_sets:is_element({F,A}, St#expand.defined).
+ Ctype = foldl(fun(F, A) ->
+ A#{F=>{imported,Mod}}
+ end, Ctype0, Fs),
+ St#expand{ctype=Ctype}.
diff --git a/lib/compiler/src/v3_kernel.erl b/lib/compiler/src/v3_kernel.erl
index 7ee564683b..011748df3a 100644
--- a/lib/compiler/src/v3_kernel.erl
+++ b/lib/compiler/src/v3_kernel.erl
@@ -117,7 +117,7 @@ copy_anno(Kdst, Ksrc) ->
fcount=0, %Fun counter
ds=cerl_sets:new() :: cerl_sets:set(), %Defined variables
funs=[], %Fun functions
- free=[], %Free variables
+ free=#{}, %Free variables
ws=[] :: [warning()], %Warnings.
guard_refc=0}). %> 0 means in guard
@@ -1837,14 +1837,17 @@ handle_reuse_anno_1(V, _St) -> V.
%% get_free(Name, Arity, State) -> [Free].
%% store_free(Name, Arity, [Free], State) -> State.
-get_free(F, A, St) ->
- case orddict:find({F,A}, St#kern.free) of
- {ok,Val} -> Val;
- error -> []
+get_free(F, A, #kern{free=FreeMap}) ->
+ Key = {F,A},
+ case FreeMap of
+ #{Key:=Val} -> Val;
+ _ -> []
end.
-store_free(F, A, Free, St) ->
- St#kern{free=orddict:store({F,A}, Free, St#kern.free)}.
+store_free(F, A, Free, #kern{free=FreeMap0}=St) ->
+ Key = {F,A},
+ FreeMap = FreeMap0#{Key=>Free},
+ St#kern{free=FreeMap}.
break_rets({break,Rs}) -> Rs;
break_rets(return) -> [].
diff --git a/lib/compiler/test/bs_match_SUITE.erl b/lib/compiler/test/bs_match_SUITE.erl
index a19b152bc5..667c6754ee 100644
--- a/lib/compiler/test/bs_match_SUITE.erl
+++ b/lib/compiler/test/bs_match_SUITE.erl
@@ -36,7 +36,8 @@
match_string/1,zero_width/1,bad_size/1,haystack/1,
cover_beam_bool/1,matched_out_size/1,follow_fail_branch/1,
no_partition/1,calling_a_binary/1,binary_in_map/1,
- match_string_opt/1,select_on_integer/1]).
+ match_string_opt/1,select_on_integer/1,
+ map_and_binary/1]).
-export([coverage_id/1,coverage_external_ignore/2]).
@@ -62,7 +63,8 @@ groups() ->
otp_7498,match_string,zero_width,bad_size,haystack,
cover_beam_bool,matched_out_size,follow_fail_branch,
no_partition,calling_a_binary,binary_in_map,
- match_string_opt,select_on_integer]}].
+ match_string_opt,select_on_integer,
+ map_and_binary]}].
init_per_suite(Config) ->
@@ -116,9 +118,16 @@ fun_shadow_4(L) ->
int_float(Config) when is_list(Config) ->
%% OTP-5323
- ?line <<103133.0:64/float>> = <<103133:64/float>>,
- ?line <<103133:64/float>> = <<103133:64/float>>,
- ok.
+ <<103133.0:64/float>> = <<103133:64/float>>,
+ <<103133:64/float>> = <<103133:64/float>>,
+
+ %% Coverage of error cases in sys_pre_expand:coerce_to_float/2.
+ case id(default) of
+ <<(1 bsl 1024):64/float>> ->
+ ?t:fail();
+ default ->
+ ok
+ end.
%% Stolen from erl_eval_SUITE and modified.
%% OTP-5269. Bugs in the bit syntax.
@@ -1240,6 +1249,25 @@ do_select_on_integer(<<0:1,I:7>>) ->
do_select_on_integer(<<1:1,_:7,Bin/binary>>) ->
Bin.
+%% If 'bin_opt_info' was given the warning would lack filename
+%% and line number.
+
+map_and_binary(_Config) ->
+ {<<"10">>,<<"37">>,<<"am">>} = do_map_and_binary(<<"10:37am">>),
+ Map1 = #{time => "noon"},
+ {ok,Map1} = do_map_and_binary(Map1),
+ Map2 = #{hour => 8, min => 42},
+ {8,42,Map2} = do_map_and_binary(Map2),
+ ok.
+
+do_map_and_binary(<<Hour:2/bytes, $:, Min:2/bytes, Rest/binary>>) ->
+ {Hour, Min, Rest};
+do_map_and_binary(#{time := _} = T) ->
+ {ok, T};
+do_map_and_binary(#{hour := Hour, min := Min} = T) ->
+ {Hour, Min, T}.
+
+
check(F, R) ->
R = F().
diff --git a/lib/compiler/test/map_SUITE.erl b/lib/compiler/test/map_SUITE.erl
index 411b15eebe..b3cafe4ed9 100644
--- a/lib/compiler/test/map_SUITE.erl
+++ b/lib/compiler/test/map_SUITE.erl
@@ -1882,7 +1882,7 @@ register_corruption_dummy_call(A,B,C) -> {A,B,C}.
t_frequency_table(Config) when is_list(Config) ->
- random:seed({13,1337,54}), % pseudo random
+ rand:seed(exsplus, {13,1337,54}), % pseudo random
N = 100000,
Ts = rand_terms(N),
#{ n:=N, tf := Tf } = frequency_table(Ts,#{ n=>0, tf => #{}}),
@@ -1925,7 +1925,7 @@ rand_terms(0) -> [];
rand_terms(N) -> [rand_term()|rand_terms(N-1)].
rand_term() ->
- case random:uniform(6) of
+ case rand:uniform(6) of
1 -> rand_binary();
2 -> rand_number();
3 -> rand_atom();
@@ -1935,21 +1935,21 @@ rand_term() ->
end.
rand_binary() ->
- case random:uniform(3) of
+ case rand:uniform(3) of
1 -> <<>>;
2 -> <<"hi">>;
3 -> <<"message text larger than 64 bytes. yep, message text larger than 64 bytes.">>
end.
rand_number() ->
- case random:uniform(3) of
- 1 -> random:uniform(5);
- 2 -> float(random:uniform(5));
- 3 -> 1 bsl (63 + random:uniform(3))
+ case rand:uniform(3) of
+ 1 -> rand:uniform(5);
+ 2 -> float(rand:uniform(5));
+ 3 -> 1 bsl (63 + rand:uniform(3))
end.
rand_atom() ->
- case random:uniform(3) of
+ case rand:uniform(3) of
1 -> hi;
2 -> some_atom;
3 -> some_other_atom
@@ -1957,21 +1957,21 @@ rand_atom() ->
rand_tuple() ->
- case random:uniform(3) of
+ case rand:uniform(3) of
1 -> {ok, rand_term()}; % careful
2 -> {1, 2, 3};
3 -> {<<"yep">>, 1337}
end.
rand_list() ->
- case random:uniform(3) of
+ case rand:uniform(3) of
1 -> "hi";
2 -> [1,rand_term()]; % careful
3 -> [improper|list]
end.
rand_map() ->
- case random:uniform(3) of
+ case rand:uniform(3) of
1 -> #{ hi => 3 };
2 -> #{ wat => rand_term(), other => 3 }; % careful
3 -> #{ hi => 42, other => 42, yet_anoter => 1337 }
diff --git a/lib/compiler/test/match_SUITE.erl b/lib/compiler/test/match_SUITE.erl
index 67d668f650..9166726aa2 100644
--- a/lib/compiler/test/match_SUITE.erl
+++ b/lib/compiler/test/match_SUITE.erl
@@ -449,7 +449,10 @@ do_map_vars_used(X, Y, Map) ->
coverage(Config) when is_list(Config) ->
%% Cover beam_dead.
ok = coverage_1(x, a),
- ok = coverage_1(x, b).
+ ok = coverage_1(x, b),
+
+ %% Cover sys_pre_expand.
+ ok = coverage_3("abc").
coverage_1(B, Tag) ->
case Tag of
@@ -460,4 +463,6 @@ coverage_1(B, Tag) ->
coverage_2(1, a, x) -> ok;
coverage_2(2, b, x) -> ok.
+coverage_3([$a]++[]++"bc") -> ok.
+
id(I) -> I.
diff --git a/lib/compiler/test/misc_SUITE.erl b/lib/compiler/test/misc_SUITE.erl
index b88abaf62d..a8b4ed0a24 100644
--- a/lib/compiler/test/misc_SUITE.erl
+++ b/lib/compiler/test/misc_SUITE.erl
@@ -38,7 +38,11 @@
-compile({no_auto_import,[byte_size/1]}).
-import(erlang,[byte_size/1]).
-
+%% Cover the code for callback handling.
+-callback must_define_this_one() -> 'ok'.
+-callback do_something_strange(atom()) -> 'ok'.
+-optional_callbacks([do_something_strange/1]).
+-optional_callbacks([ignore_me]). %Invalid; ignored.
%% Include an opaque declaration to cover the stripping of
%% opaque types from attributes in v3_kernel.
@@ -385,9 +389,9 @@ integer_encoding_1(Config) ->
do_integer_encoding(0, _, _, _) -> ok;
do_integer_encoding(N, I0, Src, Data) ->
- I1 = (I0 bsl 5) bor (random:uniform(32) - 1),
+ I1 = (I0 bsl 5) bor (rand:uniform(32) - 1),
do_integer_encoding(I1, Src, Data),
- I2 = -(I1 bxor (random:uniform(32) - 1)),
+ I2 = -(I1 bxor (rand:uniform(32) - 1)),
do_integer_encoding(I2, Src, Data),
do_integer_encoding(N-1, I1, Src, Data).
diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c
index e9cac30c9c..bb2771163d 100644
--- a/lib/crypto/c_src/crypto.c
+++ b/lib/crypto/c_src/crypto.c
@@ -91,6 +91,7 @@
#endif
#if OPENSSL_VERSION_NUMBER >= 0x1000100fL
+# define HAVE_EVP_AES_CTR
# define HAVE_GCM
#endif
@@ -98,6 +99,10 @@
# define HAVE_CHACHA20_POLY1305
#endif
+#if OPENSSL_VERSION_NUMBER <= 0x009080cfL
+# define HAVE_ECB_IVEC_BUG
+#endif
+
#if defined(HAVE_EC)
#include <openssl/ec.h>
#include <openssl/ecdh.h>
@@ -193,57 +198,20 @@ static void unload(ErlNifEnv* env, void* priv_data);
/* The NIFs: */
static ERL_NIF_TERM info_lib(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM algorithms(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM md5(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM md5_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM md5_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM md5_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM ripemd160(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM ripemd160_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM ripemd160_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM ripemd160_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha224_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha224_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha224_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha224_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha256_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha256_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha256_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha256_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha384_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha384_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha384_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha384_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha512_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha512_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha512_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha512_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM md4(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM md4_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM md4_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM md4_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM md5_mac_n(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha_mac_n(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha224_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha256_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha384_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha512_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM hmac_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM hmac_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM hmac_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM des_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM des_cfb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM des_ecb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM des_ede3_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM des_ede3_cfb_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM hash_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM hash_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM hash_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM hash_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM hmac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM hmac_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM hmac_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM hmac_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM block_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM aes_cfb_8_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM aes_cfb_128_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM aes_ige_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM aes_ctr_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM aes_ctr_stream_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM aes_ctr_stream_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM aes_ecb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rand_bytes_1(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM strong_rand_bytes_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rand_bytes_3(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
@@ -252,13 +220,10 @@ static ERL_NIF_TERM rand_uniform_nif(ErlNifEnv* env, int argc, const ERL_NIF_TER
static ERL_NIF_TERM mod_exp_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM dss_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM aes_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM aes_ige_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM do_exor(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rc4_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rc4_set_key(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rc4_encrypt_with_state(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM rc2_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM dss_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rsa_public_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
@@ -270,10 +235,6 @@ static ERL_NIF_TERM dh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_T
static ERL_NIF_TERM srp_value_B_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM srp_user_secret_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM srp_host_secret_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM bf_cfb64_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM bf_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM bf_ecb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM blowfish_ofb64_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM ec_key_generate(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM ecdsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
@@ -291,32 +252,7 @@ static ERL_NIF_TERM chacha20_poly1305_decrypt(ErlNifEnv* env, int argc, const ER
/* helpers */
static void init_algorithms_types(ErlNifEnv*);
static void init_digest_types(ErlNifEnv* env);
-static void hmac_md5(unsigned char *key, int klen,
- unsigned char *dbuf, int dlen,
- unsigned char *hmacbuf);
-static void hmac_sha1(unsigned char *key, int klen,
- unsigned char *dbuf, int dlen,
- unsigned char *hmacbuf);
-#ifdef HAVE_SHA224
-static void hmac_sha224(unsigned char *key, int klen,
- unsigned char *dbuf, int dlen,
- unsigned char *hmacbuf);
-#endif
-#ifdef HAVE_SHA256
-static void hmac_sha256(unsigned char *key, int klen,
- unsigned char *dbuf, int dlen,
- unsigned char *hmacbuf);
-#endif
-#ifdef HAVE_SHA384
-static void hmac_sha384(unsigned char *key, int klen,
- unsigned char *dbuf, int dlen,
- unsigned char *hmacbuf);
-#endif
-#ifdef HAVE_SHA512
-static void hmac_sha512(unsigned char *key, int klen,
- unsigned char *dbuf, int dlen,
- unsigned char *hmacbuf);
-#endif
+static void init_cipher_types(ErlNifEnv* env);
#ifdef HAVE_EC
static EC_KEY* ec_key_new(ErlNifEnv* env, ERL_NIF_TERM curve_arg);
static int term2point(ErlNifEnv* env, ERL_NIF_TERM term,
@@ -328,60 +264,25 @@ static int library_refc = 0; /* number of users of this dynamic library */
static ErlNifFunc nif_funcs[] = {
{"info_lib", 0, info_lib},
{"algorithms", 0, algorithms},
- {"md5", 1, md5},
- {"md5_init", 0, md5_init},
- {"md5_update", 2, md5_update},
- {"md5_final", 1, md5_final},
- {"ripemd160", 1, ripemd160},
- {"ripemd160_init", 0, ripemd160_init},
- {"ripemd160_update", 2, ripemd160_update},
- {"ripemd160_final", 1, ripemd160_final},
- {"sha", 1, sha},
- {"sha_init", 0, sha_init},
- {"sha_update", 2, sha_update},
- {"sha_final", 1, sha_final},
- {"sha224_nif", 1, sha224_nif},
- {"sha224_init_nif", 0, sha224_init_nif},
- {"sha224_update_nif", 2, sha224_update_nif},
- {"sha224_final_nif", 1, sha224_final_nif},
- {"sha256_nif", 1, sha256_nif},
- {"sha256_init_nif", 0, sha256_init_nif},
- {"sha256_update_nif", 2, sha256_update_nif},
- {"sha256_final_nif", 1, sha256_final_nif},
- {"sha384_nif", 1, sha384_nif},
- {"sha384_init_nif", 0, sha384_init_nif},
- {"sha384_update_nif", 2, sha384_update_nif},
- {"sha384_final_nif", 1, sha384_final_nif},
- {"sha512_nif", 1, sha512_nif},
- {"sha512_init_nif", 0, sha512_init_nif},
- {"sha512_update_nif", 2, sha512_update_nif},
- {"sha512_final_nif", 1, sha512_final_nif},
- {"md4", 1, md4},
- {"md4_init", 0, md4_init},
- {"md4_update", 2, md4_update},
- {"md4_final", 1, md4_final},
- {"md5_mac_n", 3, md5_mac_n},
- {"sha_mac_n", 3, sha_mac_n},
- {"sha224_mac_nif", 3, sha224_mac_nif},
- {"sha256_mac_nif", 3, sha256_mac_nif},
- {"sha384_mac_nif", 3, sha384_mac_nif},
- {"sha512_mac_nif", 3, sha512_mac_nif},
- {"hmac_init", 2, hmac_init},
- {"hmac_update", 2, hmac_update},
- {"hmac_final", 1, hmac_final},
- {"hmac_final_n", 2, hmac_final},
- {"des_cbc_crypt", 4, des_cbc_crypt},
- {"des_cfb_crypt", 4, des_cfb_crypt},
- {"des_ecb_crypt", 3, des_ecb_crypt},
- {"des_ede3_cbc_crypt", 6, des_ede3_cbc_crypt},
- {"des_ede3_cfb_crypt_nif", 6, des_ede3_cfb_crypt_nif},
- {"aes_cfb_8_crypt", 4, aes_cfb_8_crypt},
- {"aes_cfb_128_crypt", 4, aes_cfb_128_crypt},
+ {"hash_nif", 2, hash_nif},
+ {"hash_init_nif", 1, hash_init_nif},
+ {"hash_update_nif", 2, hash_update_nif},
+ {"hash_final_nif", 1, hash_final_nif},
+ {"hmac_nif", 3, hmac_nif},
+ {"hmac_nif", 4, hmac_nif},
+ {"hmac_init_nif", 2, hmac_init_nif},
+ {"hmac_update_nif", 2, hmac_update_nif},
+ {"hmac_final_nif", 1, hmac_final_nif},
+ {"hmac_final_nif", 2, hmac_final_nif},
+ {"block_crypt_nif", 5, block_crypt_nif},
+ {"block_crypt_nif", 4, block_crypt_nif},
+ {"aes_ige_crypt_nif", 4, aes_ige_crypt_nif},
+
{"aes_ctr_encrypt", 3, aes_ctr_encrypt},
{"aes_ctr_decrypt", 3, aes_ctr_encrypt},
+ {"aes_ctr_stream_init", 2, aes_ctr_stream_init},
{"aes_ctr_stream_encrypt", 2, aes_ctr_stream_encrypt},
{"aes_ctr_stream_decrypt", 2, aes_ctr_stream_encrypt},
- {"aes_ecb_crypt", 3, aes_ecb_crypt},
{"rand_bytes", 1, rand_bytes_1},
{"strong_rand_bytes_nif", 1, strong_rand_bytes_nif},
{"rand_bytes", 3, rand_bytes_3},
@@ -390,13 +291,10 @@ static ErlNifFunc nif_funcs[] = {
{"mod_exp_nif", 4, mod_exp_nif},
{"dss_verify_nif", 4, dss_verify_nif},
{"rsa_verify_nif", 4, rsa_verify_nif},
- {"aes_cbc_crypt", 4, aes_cbc_crypt},
- {"aes_ige_crypt_nif", 4, aes_ige_crypt_nif},
{"do_exor", 2, do_exor},
{"rc4_encrypt", 2, rc4_encrypt},
{"rc4_set_key", 1, rc4_set_key},
{"rc4_encrypt_with_state", 2, rc4_encrypt_with_state},
- {"rc2_cbc_crypt", 4, rc2_cbc_crypt},
{"rsa_sign_nif", 3, rsa_sign_nif},
{"dss_sign_nif", 3, dss_sign_nif},
{"rsa_public_crypt", 4, rsa_public_crypt},
@@ -408,10 +306,6 @@ static ErlNifFunc nif_funcs[] = {
{"srp_value_B_nif", 5, srp_value_B_nif},
{"srp_user_secret_nif", 7, srp_user_secret_nif},
{"srp_host_secret_nif", 5, srp_host_secret_nif},
- {"bf_cfb64_crypt", 4, bf_cfb64_crypt},
- {"bf_cbc_crypt", 4, bf_cbc_crypt},
- {"bf_ecb_crypt", 3, bf_ecb_crypt},
- {"blowfish_ofb64_encrypt", 3, blowfish_ofb64_encrypt},
{"ec_key_generate", 2, ec_key_generate},
{"ecdsa_sign_nif", 4, ecdsa_sign_nif},
@@ -432,37 +326,14 @@ static ErlNifFunc nif_funcs[] = {
ERL_NIF_INIT(crypto,nif_funcs,load,NULL,upgrade,unload)
-#define MD5_CTX_LEN (sizeof(MD5_CTX))
-#define MD5_LEN 16
-#define MD5_LEN_96 12
-#define MD4_CTX_LEN (sizeof(MD4_CTX))
-#define MD4_LEN 16
+#define MD5_CTX_LEN (sizeof(MD5_CTX))
+#define MD4_CTX_LEN (sizeof(MD4_CTX))
#define RIPEMD160_CTX_LEN (sizeof(RIPEMD160_CTX))
-#define RIPEMD160_LEN 20
-#define SHA_CTX_LEN (sizeof(SHA_CTX))
-#define SHA_LEN 20
-#define SHA_LEN_96 12
-#define SHA224_LEN (224/8)
-#define SHA256_LEN (256/8)
-#define SHA384_LEN (384/8)
-#define SHA512_LEN (512/8)
-#define HMAC_INT_LEN 64
-#define HMAC_INT2_LEN 128
-
-#define HMAC_IPAD 0x36
-#define HMAC_OPAD 0x5c
static ERL_NIF_TERM atom_true;
static ERL_NIF_TERM atom_false;
static ERL_NIF_TERM atom_sha;
-static ERL_NIF_TERM atom_sha224;
-static ERL_NIF_TERM atom_sha256;
-static ERL_NIF_TERM atom_sha384;
-static ERL_NIF_TERM atom_sha512;
-static ERL_NIF_TERM atom_md5;
-static ERL_NIF_TERM atom_md4;
-static ERL_NIF_TERM atom_ripemd160;
static ERL_NIF_TERM atom_error;
static ERL_NIF_TERM atom_rsa_pkcs1_padding;
static ERL_NIF_TERM atom_rsa_pkcs1_oaep_padding;
@@ -489,6 +360,14 @@ static ERL_NIF_TERM atom_ppbasis;
static ERL_NIF_TERM atom_onbasis;
#endif
+static ERL_NIF_TERM atom_aes_cfb8;
+static ERL_NIF_TERM atom_aes_cfb128;
+#ifdef HAVE_ECB_IVEC_BUG
+static ERL_NIF_TERM atom_aes_ecb;
+static ERL_NIF_TERM atom_des_ecb;
+static ERL_NIF_TERM atom_blowfish_ecb;
+#endif
+
static ErlNifResourceType* hmac_context_rtype;
struct hmac_context
{
@@ -498,6 +377,87 @@ struct hmac_context
};
static void hmac_context_dtor(ErlNifEnv* env, struct hmac_context*);
+struct digest_type_t {
+ const char* type_str;
+ const EVP_MD* (*md_func)(void); /* NULL if notsup */
+ ERL_NIF_TERM type_atom;
+};
+
+struct digest_type_t digest_types[] =
+{
+ {"md4", &EVP_md4},
+ {"md5", &EVP_md5},
+ {"ripemd160", &EVP_ripemd160},
+ {"sha", &EVP_sha1},
+ {"sha224",
+#ifdef HAVE_SHA224
+ &EVP_sha224
+#else
+ NULL
+#endif
+ },
+ {"sha256",
+#ifdef HAVE_SHA256
+ &EVP_sha256
+#else
+ NULL
+#endif
+ },
+ {"sha384",
+#ifdef HAVE_SHA384
+ &EVP_sha384
+#else
+ NULL
+#endif
+ },
+ {"sha512",
+#ifdef HAVE_SHA512
+ &EVP_sha512
+#else
+ NULL
+#endif
+ },
+ {NULL}
+};
+
+static struct digest_type_t* get_digest_type(ERL_NIF_TERM type);
+
+struct cipher_type_t {
+ const char* type_str;
+ const EVP_CIPHER* (*cipher_func)(void); /* NULL if notsup */
+ const size_t key_len; /* != 0 to also match on key_len */
+ ERL_NIF_TERM type_atom;
+};
+
+struct cipher_type_t cipher_types[] =
+{
+ {"rc2_cbc", &EVP_rc2_cbc},
+ {"des_cbc", &EVP_des_cbc},
+ {"des_cfb", &EVP_des_cfb8},
+ {"des_ecb", &EVP_des_ecb},
+ {"des_ede3_cbc", &EVP_des_ede3_cbc},
+ {"des_ede3_cbf",
+#ifdef HAVE_DES_ede3_cfb_encrypt
+ &EVP_des_ede3_cfb8
+#else
+ NULL
+#endif
+ },
+ {"blowfish_cbc", &EVP_bf_cbc},
+ {"blowfish_cfb64", &EVP_bf_cfb64},
+ {"blowfish_ofb64", &EVP_bf_ofb},
+ {"blowfish_ecb", &EVP_bf_ecb},
+ {"aes_cbc128", &EVP_aes_128_cbc},
+ {"aes_cbc256", &EVP_aes_256_cbc},
+ {"aes_cfb8", &EVP_aes_128_cfb8},
+ {"aes_cfb128", &EVP_aes_128_cfb128},
+ {"aes_ecb", &EVP_aes_128_ecb, 16},
+ {"aes_ecb", &EVP_aes_256_ecb, 32},
+ {NULL}
+};
+
+static struct cipher_type_t* get_cipher_type(ERL_NIF_TERM type, size_t key_len);
+
/*
#define PRINTF_ERR0(FMT) enif_fprintf(stderr, FMT "\n")
#define PRINTF_ERR1(FMT, A1) enif_fprintf(stderr, FMT "\n", A1)
@@ -507,6 +467,21 @@ static void hmac_context_dtor(ErlNifEnv* env, struct hmac_context*);
#define PRINTF_ERR1(FMT,A1)
#define PRINTF_ERR2(FMT,A1,A2)
+#if OPENSSL_VERSION_NUMBER >= 0x1000000fL
+/* Define resource types for OpenSSL context structures. */
+static ErlNifResourceType* evp_md_ctx_rtype;
+static void evp_md_ctx_dtor(ErlNifEnv* env, EVP_MD_CTX* ctx) {
+ EVP_MD_CTX_cleanup(ctx);
+}
+#endif
+
+#ifdef HAVE_EVP_AES_CTR
+static ErlNifResourceType* evp_cipher_ctx_rtype;
+static void evp_cipher_ctx_dtor(ErlNifEnv* env, EVP_CIPHER_CTX* ctx) {
+ EVP_CIPHER_CTX_cleanup(ctx);
+}
+#endif
+
static int verify_lib_version(void)
{
const unsigned long libv = SSLeay();
@@ -522,7 +497,6 @@ static int verify_lib_version(void)
return 1;
}
-
#ifdef HAVE_DYNAMIC_CRYPTO_LIB
# if defined(DEBUG)
@@ -558,7 +532,9 @@ static void error_handler(void* null, const char* errstr)
static int init(ErlNifEnv* env, ERL_NIF_TERM load_info)
{
+#ifdef OPENSSL_THREADS
ErlNifSysInfo sys_info;
+#endif
get_crypto_callbacks_t* funcp;
struct crypto_callbacks* ccb;
int nlocks = 0;
@@ -590,7 +566,26 @@ static int init(ErlNifEnv* env, ERL_NIF_TERM load_info)
PRINTF_ERR0("CRYPTO: Could not open resource type 'hmac_context'");
return 0;
}
-
+#if OPENSSL_VERSION_NUMBER >= 0x1000000fL
+ evp_md_ctx_rtype = enif_open_resource_type(env, NULL, "EVP_MD_CTX",
+ (ErlNifResourceDtor*) evp_md_ctx_dtor,
+ ERL_NIF_RT_CREATE|ERL_NIF_RT_TAKEOVER,
+ NULL);
+ if (!evp_md_ctx_rtype) {
+ PRINTF_ERR0("CRYPTO: Could not open resource type 'EVP_MD_CTX'");
+ return 0;
+ }
+#endif
+#ifdef HAVE_EVP_AES_CTR
+ evp_cipher_ctx_rtype = enif_open_resource_type(env, NULL, "EVP_CIPHER_CTX",
+ (ErlNifResourceDtor*) evp_cipher_ctx_dtor,
+ ERL_NIF_RT_CREATE|ERL_NIF_RT_TAKEOVER,
+ NULL);
+ if (!evp_cipher_ctx_rtype) {
+ PRINTF_ERR0("CRYPTO: Could not open resource type 'EVP_CIPHER_CTX'");
+ return 0;
+ }
+#endif
if (library_refc > 0) {
/* Repeated loading of this library (module upgrade).
* Atoms and callbacks are already set, we are done.
@@ -598,16 +593,9 @@ static int init(ErlNifEnv* env, ERL_NIF_TERM load_info)
return 1;
}
- atom_true = enif_make_atom(env,"true");
+ atom_true = enif_make_atom(env,"true");
atom_false = enif_make_atom(env,"false");
atom_sha = enif_make_atom(env,"sha");
- atom_sha224 = enif_make_atom(env,"sha224");
- atom_sha256 = enif_make_atom(env,"sha256");
- atom_sha384 = enif_make_atom(env,"sha384");
- atom_sha512 = enif_make_atom(env,"sha512");
- atom_md4 = enif_make_atom(env,"md4");
- atom_md5 = enif_make_atom(env,"md5");
- atom_ripemd160 = enif_make_atom(env,"ripemd160");
atom_error = enif_make_atom(env,"error");
atom_rsa_pkcs1_padding = enif_make_atom(env,"rsa_pkcs1_padding");
atom_rsa_pkcs1_oaep_padding = enif_make_atom(env,"rsa_pkcs1_oaep_padding");
@@ -632,8 +620,16 @@ static int init(ErlNifEnv* env, ERL_NIF_TERM load_info)
atom_ppbasis = enif_make_atom(env,"ppbasis");
atom_onbasis = enif_make_atom(env,"onbasis");
#endif
+ atom_aes_cfb8 = enif_make_atom(env, "aes_cfb8");
+ atom_aes_cfb128 = enif_make_atom(env, "aes_cfb128");
+#ifdef HAVE_ECB_IVEC_BUG
+ atom_aes_ecb = enif_make_atom(env, "aes_ecb");
+ atom_des_ecb = enif_make_atom(env, "des_ecb");
+ atom_blowfish_ecb = enif_make_atom(env, "blowfish_ecb");
+#endif
init_digest_types(env);
+ init_cipher_types(env);
init_algorithms_types(env);
#ifdef HAVE_DYNAMIC_CRYPTO_LIB
@@ -718,46 +714,66 @@ static void unload(ErlNifEnv* env, void* priv_data)
static int algo_hash_cnt;
static ERL_NIF_TERM algo_hash[8]; /* increase when extending the list */
static int algo_pubkey_cnt;
-static ERL_NIF_TERM algo_pubkey[3]; /* increase when extending the list */
+static ERL_NIF_TERM algo_pubkey[7]; /* increase when extending the list */
static int algo_cipher_cnt;
-static ERL_NIF_TERM algo_cipher[4]; /* increase when extending the list */
+static ERL_NIF_TERM algo_cipher[20]; /* increase when extending the list */
static void init_algorithms_types(ErlNifEnv* env)
{
algo_hash_cnt = 0;
- algo_hash[algo_hash_cnt++] = atom_md4;
- algo_hash[algo_hash_cnt++] = atom_md5;
algo_hash[algo_hash_cnt++] = atom_sha;
- algo_hash[algo_hash_cnt++] = atom_ripemd160;
#ifdef HAVE_SHA224
- algo_hash[algo_hash_cnt++] = atom_sha224;
+ algo_hash[algo_hash_cnt++] = enif_make_atom(env, "sha224");
#endif
#ifdef HAVE_SHA256
- algo_hash[algo_hash_cnt++] = atom_sha256;
+ algo_hash[algo_hash_cnt++] = enif_make_atom(env, "sha256");
#endif
#ifdef HAVE_SHA384
- algo_hash[algo_hash_cnt++] = atom_sha384;
+ algo_hash[algo_hash_cnt++] = enif_make_atom(env, "sha384");
#endif
#ifdef HAVE_SHA512
- algo_hash[algo_hash_cnt++] = atom_sha512;
+ algo_hash[algo_hash_cnt++] = enif_make_atom(env, "sha512");
#endif
+ algo_hash[algo_hash_cnt++] = enif_make_atom(env, "md4");
+ algo_hash[algo_hash_cnt++] = enif_make_atom(env, "md5");
+ algo_hash[algo_hash_cnt++] = enif_make_atom(env, "ripemd160");
algo_pubkey_cnt = 0;
+ algo_pubkey[algo_pubkey_cnt++] = enif_make_atom(env, "rsa");
+ algo_pubkey[algo_pubkey_cnt++] = enif_make_atom(env, "dss");
+ algo_pubkey[algo_pubkey_cnt++] = enif_make_atom(env, "dh");
#if defined(HAVE_EC)
#if !defined(OPENSSL_NO_EC2M)
- algo_pubkey[algo_pubkey_cnt++] = enif_make_atom(env,"ec_gf2m");
+ algo_pubkey[algo_pubkey_cnt++] = enif_make_atom(env, "ec_gf2m");
#endif
- algo_pubkey[algo_pubkey_cnt++] = enif_make_atom(env,"ecdsa");
- algo_pubkey[algo_pubkey_cnt++] = enif_make_atom(env,"ecdh");
+ algo_pubkey[algo_pubkey_cnt++] = enif_make_atom(env, "ecdsa");
+ algo_pubkey[algo_pubkey_cnt++] = enif_make_atom(env, "ecdh");
#endif
+ algo_pubkey[algo_pubkey_cnt++] = enif_make_atom(env, "srp");
algo_cipher_cnt = 0;
+ algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "des3_cbc");
+ algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "des_ede3");
#ifdef HAVE_DES_ede3_cfb_encrypt
algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "des3_cbf");
#endif
+ algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "aes_cbc128");
+ algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "aes_cfb8");
+ algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "aes_cfb128");
+ algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "aes_cbc256");
+ algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "aes_ctr");
+ algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "aes_ecb");
#ifdef HAVE_AES_IGE
algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"aes_ige256");
#endif
+ algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"des_cbc");
+ algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"des_cfb");
+ algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"blowfish_cbc");
+ algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"blowfish_cfb64");
+ algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"blowfish_ofb64");
+ algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"blowfish_ecb");
+ algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"rc2_cbc");
+ algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"rc4");
#if defined(HAVE_GCM)
algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"aes_gcm");
#endif
@@ -772,10 +788,13 @@ static void init_algorithms_types(ErlNifEnv* env)
static ERL_NIF_TERM algorithms(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
+ int hash_cnt = algo_hash_cnt;
+ int pubkey_cnt = algo_pubkey_cnt;
+ int cipher_cnt = algo_cipher_cnt;
return enif_make_tuple3(env,
- enif_make_list_from_array(env, algo_hash, algo_hash_cnt),
- enif_make_list_from_array(env, algo_pubkey, algo_pubkey_cnt),
- enif_make_list_from_array(env, algo_cipher, algo_cipher_cnt));
+ enif_make_list_from_array(env, algo_hash, hash_cnt),
+ enif_make_list_from_array(env, algo_pubkey, pubkey_cnt),
+ enif_make_list_from_array(env, algo_cipher, cipher_cnt));
}
static ERL_NIF_TERM info_lib(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
@@ -805,564 +824,383 @@ static ERL_NIF_TERM info_lib(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]
ver_term));
}
-static ERL_NIF_TERM md5(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Data) */
- ErlNifBinary ibin;
- ERL_NIF_TERM ret;
- if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) {
- return enif_make_badarg(env);
- }
- MD5((unsigned char *) ibin.data, ibin.size,
- enif_make_new_binary(env,MD5_LEN, &ret));
- CONSUME_REDS(env,ibin);
- return ret;
-}
-static ERL_NIF_TERM md5_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* () */
- ERL_NIF_TERM ret;
- MD5_Init((MD5_CTX *) enif_make_new_binary(env, MD5_CTX_LEN, &ret));
- return ret;
-}
-static ERL_NIF_TERM md5_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Context, Data) */
- MD5_CTX* new_ctx;
- ErlNifBinary ctx_bin, data_bin;
- ERL_NIF_TERM ret;
- if (!enif_inspect_binary(env, argv[0], &ctx_bin)
- || ctx_bin.size != MD5_CTX_LEN
- || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) {
+static ERL_NIF_TERM hash_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Type, Data) */
+ struct digest_type_t *digp = NULL;
+ const EVP_MD *md;
+ ErlNifBinary data;
+ ERL_NIF_TERM ret;
+ unsigned ret_size;
+
+ digp = get_digest_type(argv[0]);
+ if (!digp ||
+ !enif_inspect_iolist_as_binary(env, argv[1], &data)) {
return enif_make_badarg(env);
}
- new_ctx = (MD5_CTX*) enif_make_new_binary(env,MD5_CTX_LEN, &ret);
- memcpy(new_ctx, ctx_bin.data, MD5_CTX_LEN);
- MD5_Update(new_ctx, data_bin.data, data_bin.size);
- CONSUME_REDS(env,data_bin);
- return ret;
-}
-static ERL_NIF_TERM md5_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Context) */
- ErlNifBinary ctx_bin;
- MD5_CTX ctx_clone;
- ERL_NIF_TERM ret;
- if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != MD5_CTX_LEN) {
- return enif_make_badarg(env);
+ if (!digp->md_func) {
+ return atom_notsup;
}
- memcpy(&ctx_clone, ctx_bin.data, MD5_CTX_LEN); /* writable */
- MD5_Final(enif_make_new_binary(env, MD5_LEN, &ret), &ctx_clone);
- return ret;
-}
-static ERL_NIF_TERM ripemd160(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Data) */
- ErlNifBinary ibin;
- ERL_NIF_TERM ret;
- if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) {
- return enif_make_badarg(env);
+ md = digp->md_func();
+ ret_size = (unsigned)EVP_MD_size(md);
+ ASSERT(0 < ret_size && ret_size <= EVP_MAX_MD_SIZE);
+ if (!EVP_Digest(data.data, data.size,
+ enif_make_new_binary(env, ret_size, &ret), &ret_size,
+ md, NULL)) {
+ return atom_notsup;
}
- RIPEMD160((unsigned char *) ibin.data, ibin.size,
- enif_make_new_binary(env,RIPEMD160_LEN, &ret));
- CONSUME_REDS(env,ibin);
- return ret;
-}
-static ERL_NIF_TERM ripemd160_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* () */
- ERL_NIF_TERM ret;
- RIPEMD160_Init((RIPEMD160_CTX *) enif_make_new_binary(env, RIPEMD160_CTX_LEN, &ret));
+ ASSERT(ret_size == (unsigned)EVP_MD_size(md));
+
+ CONSUME_REDS(env, data);
return ret;
}
-static ERL_NIF_TERM ripemd160_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Context, Data) */
- RIPEMD160_CTX* new_ctx;
- ErlNifBinary ctx_bin, data_bin;
- ERL_NIF_TERM ret;
- if (!enif_inspect_binary(env, argv[0], &ctx_bin)
- || ctx_bin.size != RIPEMD160_CTX_LEN
- || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) {
+
+#if OPENSSL_VERSION_NUMBER >= 0x1000000fL
+
+static ERL_NIF_TERM hash_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Type) */
+ struct digest_type_t *digp = NULL;
+ EVP_MD_CTX *ctx;
+ ERL_NIF_TERM ret;
+
+ digp = get_digest_type(argv[0]);
+ if (!digp) {
return enif_make_badarg(env);
}
- new_ctx = (RIPEMD160_CTX*) enif_make_new_binary(env,RIPEMD160_CTX_LEN, &ret);
- memcpy(new_ctx, ctx_bin.data, RIPEMD160_CTX_LEN);
- RIPEMD160_Update(new_ctx, data_bin.data, data_bin.size);
- CONSUME_REDS(env, data_bin);
- return ret;
-}
-static ERL_NIF_TERM ripemd160_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Context) */
- ErlNifBinary ctx_bin;
- RIPEMD160_CTX ctx_clone;
- ERL_NIF_TERM ret;
- if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != RIPEMD160_CTX_LEN) {
- return enif_make_badarg(env);
+ if (!digp->md_func) {
+ return atom_notsup;
}
- memcpy(&ctx_clone, ctx_bin.data, RIPEMD160_CTX_LEN); /* writable */
- RIPEMD160_Final(enif_make_new_binary(env, RIPEMD160_LEN, &ret), &ctx_clone);
- return ret;
-}
-
-static ERL_NIF_TERM sha(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Data) */
- ErlNifBinary ibin;
- ERL_NIF_TERM ret;
- if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) {
- return enif_make_badarg(env);
+ ctx = enif_alloc_resource(evp_md_ctx_rtype, sizeof(EVP_MD_CTX));
+ if (!EVP_DigestInit(ctx, digp->md_func())) {
+ enif_release_resource(ctx);
+ return atom_notsup;
}
- SHA1((unsigned char *) ibin.data, ibin.size,
- enif_make_new_binary(env,SHA_LEN, &ret));
- CONSUME_REDS(env,ibin);
- return ret;
-}
-static ERL_NIF_TERM sha_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* () */
- ERL_NIF_TERM ret;
- SHA1_Init((SHA_CTX *) enif_make_new_binary(env, SHA_CTX_LEN, &ret));
+ ret = enif_make_resource(env, ctx);
+ enif_release_resource(ctx);
return ret;
}
-static ERL_NIF_TERM sha_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+static ERL_NIF_TERM hash_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Context, Data) */
- SHA_CTX* new_ctx;
- ErlNifBinary ctx_bin, data_bin;
+ EVP_MD_CTX *ctx, *new_ctx;
+ ErlNifBinary data;
ERL_NIF_TERM ret;
- if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != SHA_CTX_LEN
- || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) {
- return enif_make_badarg(env);
+
+ if (!enif_get_resource(env, argv[0], evp_md_ctx_rtype, (void**)&ctx) ||
+ !enif_inspect_iolist_as_binary(env, argv[1], &data)) {
+ return enif_make_badarg(env);
}
- new_ctx = (SHA_CTX*) enif_make_new_binary(env,SHA_CTX_LEN, &ret);
- memcpy(new_ctx, ctx_bin.data, SHA_CTX_LEN);
- SHA1_Update(new_ctx, data_bin.data, data_bin.size);
- CONSUME_REDS(env,data_bin);
+
+ new_ctx = enif_alloc_resource(evp_md_ctx_rtype, sizeof(EVP_MD_CTX));
+ if (!EVP_MD_CTX_copy(new_ctx, ctx) ||
+ !EVP_DigestUpdate(new_ctx, data.data, data.size)) {
+ enif_release_resource(new_ctx);
+ return atom_notsup;
+ }
+
+ ret = enif_make_resource(env, new_ctx);
+ enif_release_resource(new_ctx);
+ CONSUME_REDS(env, data);
return ret;
}
-static ERL_NIF_TERM sha_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+static ERL_NIF_TERM hash_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Context) */
- ErlNifBinary ctx_bin;
- SHA_CTX ctx_clone;
- ERL_NIF_TERM ret;
- if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != SHA_CTX_LEN) {
- return enif_make_badarg(env);
+ EVP_MD_CTX *ctx, new_ctx;
+ ERL_NIF_TERM ret;
+ unsigned ret_size;
+
+ if (!enif_get_resource(env, argv[0], evp_md_ctx_rtype, (void**)&ctx)) {
+ return enif_make_badarg(env);
}
- memcpy(&ctx_clone, ctx_bin.data, SHA_CTX_LEN); /* writable */
- SHA1_Final(enif_make_new_binary(env, SHA_LEN, &ret), &ctx_clone);
- return ret;
-}
-static ERL_NIF_TERM sha224_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Data) */
-#ifdef HAVE_SHA224
- ErlNifBinary ibin;
- ERL_NIF_TERM ret;
- if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) {
- return enif_make_badarg(env);
+ ret_size = (unsigned)EVP_MD_CTX_size(ctx);
+ ASSERT(0 < ret_size && ret_size <= EVP_MAX_MD_SIZE);
+
+ if (!EVP_MD_CTX_copy(&new_ctx, ctx) ||
+ !EVP_DigestFinal(&new_ctx,
+ enif_make_new_binary(env, ret_size, &ret),
+ &ret_size)) {
+ return atom_notsup;
}
- SHA224((unsigned char *) ibin.data, ibin.size,
- enif_make_new_binary(env,SHA224_LEN, &ret));
- CONSUME_REDS(env,ibin);
- return ret;
-#else
- return atom_notsup;
-#endif
-}
-static ERL_NIF_TERM sha224_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* () */
-#ifdef HAVE_SHA224
- ERL_NIF_TERM ret;
- SHA224_Init((SHA256_CTX *) enif_make_new_binary(env, sizeof(SHA256_CTX), &ret));
+ ASSERT(ret_size == (unsigned)EVP_MD_CTX_size(ctx));
+
return ret;
-#else
- return atom_notsup;
-#endif
}
-static ERL_NIF_TERM sha224_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Context, Data) */
-#ifdef HAVE_SHA224
- SHA256_CTX* new_ctx;
- ErlNifBinary ctx_bin, data_bin;
- ERL_NIF_TERM ret;
- if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA256_CTX)
- || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) {
+
+#else /* if OPENSSL_VERSION_NUMBER < 1.0 */
+
+static ERL_NIF_TERM hash_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Type) */
+ typedef int (*init_fun)(unsigned char*);
+ struct digest_type_t *digp = NULL;
+ ERL_NIF_TERM ctx;
+ size_t ctx_size = 0;
+ init_fun ctx_init = 0;
+
+ digp = get_digest_type(argv[0]);
+ if (!digp) {
return enif_make_badarg(env);
}
- new_ctx = (SHA256_CTX*) enif_make_new_binary(env,sizeof(SHA256_CTX), &ret);
- memcpy(new_ctx, ctx_bin.data, sizeof(SHA256_CTX));
- SHA224_Update(new_ctx, data_bin.data, data_bin.size);
- CONSUME_REDS(env,data_bin);
- return ret;
-#else
- return atom_notsup;
-#endif
-}
-static ERL_NIF_TERM sha224_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Context) */
-#ifdef HAVE_SHA224
- ErlNifBinary ctx_bin;
- SHA256_CTX ctx_clone;
- ERL_NIF_TERM ret;
- if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA256_CTX)) {
- return enif_make_badarg(env);
+ if (!digp->md_func) {
+ return atom_notsup;
}
- memcpy(&ctx_clone, ctx_bin.data, sizeof(SHA256_CTX)); /* writable */
- SHA224_Final(enif_make_new_binary(env, SHA224_LEN, &ret), &ctx_clone);
- return ret;
-#else
- return atom_notsup;
-#endif
-}
-static ERL_NIF_TERM sha256_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Data) */
-#ifdef HAVE_SHA256
- ErlNifBinary ibin;
- ERL_NIF_TERM ret;
- if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) {
- return enif_make_badarg(env);
- }
- SHA256((unsigned char *) ibin.data, ibin.size,
- enif_make_new_binary(env,SHA256_LEN, &ret));
- CONSUME_REDS(env,ibin);
- return ret;
-#else
- return atom_notsup;
+ switch (EVP_MD_type(digp->md_func()))
+ {
+ case NID_md4:
+ ctx_size = MD4_CTX_LEN;
+ ctx_init = (init_fun)(&MD4_Init);
+ break;
+ case NID_md5:
+ ctx_size = MD5_CTX_LEN;
+ ctx_init = (init_fun)(&MD5_Init);
+ break;
+ case NID_ripemd160:
+ ctx_size = RIPEMD160_CTX_LEN;
+ ctx_init = (init_fun)(&RIPEMD160_Init);
+ break;
+ case NID_sha1:
+ ctx_size = sizeof(SHA_CTX);
+ ctx_init = (init_fun)(&SHA1_Init);
+ break;
+#ifdef HAVE_SHA224
+ case NID_sha224:
+ ctx_size = sizeof(SHA256_CTX);
+ ctx_init = (init_fun)(&SHA224_Init);
+ break;
#endif
-}
-static ERL_NIF_TERM sha256_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* () */
#ifdef HAVE_SHA256
- ERL_NIF_TERM ret;
- SHA256_Init((SHA256_CTX *) enif_make_new_binary(env, sizeof(SHA256_CTX), &ret));
- return ret;
-#else
- return atom_notsup;
+ case NID_sha256:
+ ctx_size = sizeof(SHA256_CTX);
+ ctx_init = (init_fun)(&SHA256_Init);
+ break;
#endif
-}
-static ERL_NIF_TERM sha256_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Context, Data) */
-#ifdef HAVE_SHA256
- SHA256_CTX* new_ctx;
- ErlNifBinary ctx_bin, data_bin;
- ERL_NIF_TERM ret;
- if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA256_CTX)
- || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) {
- return enif_make_badarg(env);
+#ifdef HAVE_SHA384
+ case NID_sha384:
+ ctx_size = sizeof(SHA512_CTX);
+ ctx_init = (init_fun)(&SHA384_Init);
+ break;
+#endif
+#ifdef HAVE_SHA512
+ case NID_sha512:
+ ctx_size = sizeof(SHA512_CTX);
+ ctx_init = (init_fun)(&SHA512_Init);
+ break;
+#endif
+ default:
+ return atom_notsup;
+ }
+ ASSERT(ctx_size);
+ ASSERT(ctx_init);
+
+ ctx_init(enif_make_new_binary(env, ctx_size, &ctx));
+ return enif_make_tuple2(env, argv[0], ctx);
+}
+static ERL_NIF_TERM hash_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* ({Type, Context}, Data) */
+ typedef int (*update_fun)(unsigned char*, const unsigned char*, size_t);
+ ERL_NIF_TERM new_ctx;
+ ErlNifBinary ctx, data;
+ const ERL_NIF_TERM *tuple;
+ int arity;
+ struct digest_type_t *digp = NULL;
+ unsigned char *ctx_buff;
+ size_t ctx_size = 0;
+ update_fun ctx_update = 0;
+
+ if (!enif_get_tuple(env, argv[0], &arity, &tuple) ||
+ arity != 2 ||
+ !(digp = get_digest_type(tuple[0])) ||
+ !enif_inspect_binary(env, tuple[1], &ctx) ||
+ !enif_inspect_iolist_as_binary(env, argv[1], &data)) {
+ return enif_make_badarg(env);
}
- new_ctx = (SHA256_CTX*) enif_make_new_binary(env,sizeof(SHA256_CTX), &ret);
- memcpy(new_ctx, ctx_bin.data, sizeof(SHA256_CTX));
- SHA256_Update(new_ctx, data_bin.data, data_bin.size);
- CONSUME_REDS(env,data_bin);
- return ret;
-#else
- return atom_notsup;
+ if (!digp->md_func) {
+ return atom_notsup;
+ }
+
+ switch (EVP_MD_type(digp->md_func()))
+ {
+ case NID_md4:
+ ctx_size = MD4_CTX_LEN;
+ ctx_update = (update_fun)(&MD4_Update);
+ break;
+ case NID_md5:
+ ctx_size = MD5_CTX_LEN;
+ ctx_update = (update_fun)(&MD5_Update);
+ break;
+ case NID_ripemd160:
+ ctx_size = RIPEMD160_CTX_LEN;
+ ctx_update = (update_fun)(&RIPEMD160_Update);
+ break;
+ case NID_sha1:
+ ctx_size = sizeof(SHA_CTX);
+ ctx_update = (update_fun)(&SHA1_Update);
+ break;
+#ifdef HAVE_SHA224
+ case NID_sha224:
+ ctx_size = sizeof(SHA256_CTX);
+ ctx_update = (update_fun)(&SHA224_Update);
+ break;
#endif
-}
-static ERL_NIF_TERM sha256_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Context) */
#ifdef HAVE_SHA256
- ErlNifBinary ctx_bin;
- SHA256_CTX ctx_clone;
- ERL_NIF_TERM ret;
- if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA256_CTX)) {
- return enif_make_badarg(env);
- }
- memcpy(&ctx_clone, ctx_bin.data, sizeof(SHA256_CTX)); /* writable */
- SHA256_Final(enif_make_new_binary(env, SHA256_LEN, &ret), &ctx_clone);
- return ret;
-#else
- return atom_notsup;
+ case NID_sha256:
+ ctx_size = sizeof(SHA256_CTX);
+ ctx_update = (update_fun)(&SHA256_Update);
+ break;
#endif
-}
-
-static ERL_NIF_TERM sha384_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Data) */
#ifdef HAVE_SHA384
- ErlNifBinary ibin;
- ERL_NIF_TERM ret;
- if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) {
- return enif_make_badarg(env);
- }
- SHA384((unsigned char *) ibin.data, ibin.size,
- enif_make_new_binary(env,SHA384_LEN, &ret));
- CONSUME_REDS(env,ibin);
- return ret;
-#else
- return atom_notsup;
+ case NID_sha384:
+ ctx_size = sizeof(SHA512_CTX);
+ ctx_update = (update_fun)(&SHA384_Update);
+ break;
#endif
-}
-static ERL_NIF_TERM sha384_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* () */
-#ifdef HAVE_SHA384
- ERL_NIF_TERM ret;
- SHA384_Init((SHA512_CTX *) enif_make_new_binary(env, sizeof(SHA512_CTX), &ret));
- return ret;
-#else
- return atom_notsup;
+#ifdef HAVE_SHA512
+ case NID_sha512:
+ ctx_size = sizeof(SHA512_CTX);
+ ctx_update = (update_fun)(&SHA512_Update);
+ break;
#endif
-}
-static ERL_NIF_TERM sha384_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Context, Data) */
-#ifdef HAVE_SHA384
- SHA512_CTX* new_ctx;
- ErlNifBinary ctx_bin, data_bin;
- ERL_NIF_TERM ret;
- if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA512_CTX)
- || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) {
- return enif_make_badarg(env);
+ default:
+ return atom_notsup;
}
- new_ctx = (SHA512_CTX*) enif_make_new_binary(env,sizeof(SHA512_CTX), &ret);
- memcpy(new_ctx, ctx_bin.data, sizeof(SHA512_CTX));
- SHA384_Update(new_ctx, data_bin.data, data_bin.size);
- CONSUME_REDS(env,data_bin);
- return ret;
-#else
- return atom_notsup;
-#endif
-}
-static ERL_NIF_TERM sha384_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Context) */
-#ifdef HAVE_SHA384
- ErlNifBinary ctx_bin;
- SHA512_CTX ctx_clone;
- ERL_NIF_TERM ret;
- if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA512_CTX)) {
- return enif_make_badarg(env);
+ ASSERT(ctx_size);
+ ASSERT(ctx_update);
+
+ if (ctx.size != ctx_size) {
+ return enif_make_badarg(env);
}
- memcpy(&ctx_clone, ctx_bin.data, sizeof(SHA512_CTX)); /* writable */
- SHA384_Final(enif_make_new_binary(env, SHA384_LEN, &ret), &ctx_clone);
- return ret;
-#else
- return atom_notsup;
-#endif
-}
-static ERL_NIF_TERM sha512_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Data) */
-#ifdef HAVE_SHA512
- ErlNifBinary ibin;
- ERL_NIF_TERM ret;
- if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) {
- return enif_make_badarg(env);
+ ctx_buff = enif_make_new_binary(env, ctx_size, &new_ctx);
+ memcpy(ctx_buff, ctx.data, ctx_size);
+ ctx_update(ctx_buff, data.data, data.size);
+
+ CONSUME_REDS(env, data);
+ return enif_make_tuple2(env, tuple[0], new_ctx);
+}
+static ERL_NIF_TERM hash_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* ({Type, Context}) */
+ typedef int (*final_fun)(unsigned char*, void*);
+ ERL_NIF_TERM ret;
+ ErlNifBinary ctx;
+ const ERL_NIF_TERM *tuple;
+ int arity;
+ struct digest_type_t *digp = NULL;
+ const EVP_MD *md;
+ void *new_ctx;
+ size_t ctx_size = 0;
+ final_fun ctx_final = 0;
+
+ if (!enif_get_tuple(env, argv[0], &arity, &tuple) ||
+ arity != 2 ||
+ !(digp = get_digest_type(tuple[0])) ||
+ !enif_inspect_binary(env, tuple[1], &ctx)) {
+ return enif_make_badarg(env);
}
- SHA512((unsigned char *) ibin.data, ibin.size,
- enif_make_new_binary(env,SHA512_LEN, &ret));
- CONSUME_REDS(env,ibin);
- return ret;
-#else
- return atom_notsup;
+ if (!digp->md_func) {
+ return atom_notsup;
+ }
+
+ md = digp->md_func();
+
+ switch (EVP_MD_type(md))
+ {
+ case NID_md4:
+ ctx_size = MD4_CTX_LEN;
+ ctx_final = (final_fun)(&MD4_Final);
+ break;
+ case NID_md5:
+ ctx_size = MD5_CTX_LEN;
+ ctx_final = (final_fun)(&MD5_Final);
+ break;
+ case NID_ripemd160:
+ ctx_size = RIPEMD160_CTX_LEN;
+ ctx_final = (final_fun)(&RIPEMD160_Final);
+ break;
+ case NID_sha1:
+ ctx_size = sizeof(SHA_CTX);
+ ctx_final = (final_fun)(&SHA1_Final);
+ break;
+#ifdef HAVE_SHA224
+ case NID_sha224:
+ ctx_size = sizeof(SHA256_CTX);
+ ctx_final = (final_fun)(&SHA224_Final);
+ break;
#endif
-}
-static ERL_NIF_TERM sha512_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* () */
-#ifdef HAVE_SHA512
- ERL_NIF_TERM ret;
- SHA512_Init((SHA512_CTX *) enif_make_new_binary(env, sizeof(SHA512_CTX), &ret));
- return ret;
-#else
- return atom_notsup;
+#ifdef HAVE_SHA256
+ case NID_sha256:
+ ctx_size = sizeof(SHA256_CTX);
+ ctx_final = (final_fun)(&SHA256_Final);
+ break;
#endif
-}
-static ERL_NIF_TERM sha512_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Context, Data) */
-#ifdef HAVE_SHA512
- SHA512_CTX* new_ctx;
- ErlNifBinary ctx_bin, data_bin;
- ERL_NIF_TERM ret;
- if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA512_CTX)
- || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) {
- return enif_make_badarg(env);
- }
- new_ctx = (SHA512_CTX*) enif_make_new_binary(env,sizeof(SHA512_CTX), &ret);
- memcpy(new_ctx, ctx_bin.data, sizeof(SHA512_CTX));
- SHA512_Update(new_ctx, data_bin.data, data_bin.size);
- CONSUME_REDS(env,data_bin);
- return ret;
-#else
- return atom_notsup;
+#ifdef HAVE_SHA384
+ case NID_sha384:
+ ctx_size = sizeof(SHA512_CTX);
+ ctx_final = (final_fun)(&SHA384_Final);
+ break;
#endif
-}
-static ERL_NIF_TERM sha512_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Context) */
#ifdef HAVE_SHA512
- ErlNifBinary ctx_bin;
- SHA512_CTX ctx_clone;
- ERL_NIF_TERM ret;
- if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA512_CTX)) {
- return enif_make_badarg(env);
- }
- memcpy(&ctx_clone, ctx_bin.data, sizeof(SHA512_CTX)); /* writable */
- SHA512_Final(enif_make_new_binary(env, SHA512_LEN, &ret), &ctx_clone);
- return ret;
-#else
- return atom_notsup;
+ case NID_sha512:
+ ctx_size = sizeof(SHA512_CTX);
+ ctx_final = (final_fun)(&SHA512_Final);
+ break;
#endif
-}
-
-
-static ERL_NIF_TERM md4(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Data) */
- ErlNifBinary ibin;
- ERL_NIF_TERM ret;
- if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) {
- return enif_make_badarg(env);
- }
- MD4((unsigned char *) ibin.data, ibin.size,
- enif_make_new_binary(env,MD4_LEN, &ret));
- CONSUME_REDS(env,ibin);
- return ret;
-}
-static ERL_NIF_TERM md4_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* () */
- ERL_NIF_TERM ret;
- MD4_Init((MD4_CTX *) enif_make_new_binary(env, MD4_CTX_LEN, &ret));
- return ret;
-}
-static ERL_NIF_TERM md4_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Context, Data) */
- MD4_CTX* new_ctx;
- ErlNifBinary ctx_bin, data_bin;
- ERL_NIF_TERM ret;
- if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != MD4_CTX_LEN
- || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) {
- return enif_make_badarg(env);
+ default:
+ return atom_notsup;
}
- new_ctx = (MD4_CTX*) enif_make_new_binary(env,MD4_CTX_LEN, &ret);
- memcpy(new_ctx, ctx_bin.data, MD4_CTX_LEN);
- MD4_Update(new_ctx, data_bin.data, data_bin.size);
- CONSUME_REDS(env,data_bin);
- return ret;
-}
-static ERL_NIF_TERM md4_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Context) */
- ErlNifBinary ctx_bin;
- MD4_CTX ctx_clone;
- ERL_NIF_TERM ret;
- if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != MD4_CTX_LEN) {
- return enif_make_badarg(env);
- }
- memcpy(&ctx_clone, ctx_bin.data, MD4_CTX_LEN); /* writable */
- MD4_Final(enif_make_new_binary(env, MD4_LEN, &ret), &ctx_clone);
- return ret;
-}
+ ASSERT(ctx_size);
+ ASSERT(ctx_final);
-static ERL_NIF_TERM md5_mac_n(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key, Data, MacSize) */
- unsigned char hmacbuf[SHA_DIGEST_LENGTH];
- ErlNifBinary key, data;
- unsigned mac_sz;
- ERL_NIF_TERM ret;
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
- || !enif_inspect_iolist_as_binary(env, argv[1], &data)
- || !enif_get_uint(env,argv[2],&mac_sz) || mac_sz > MD5_LEN) {
- return enif_make_badarg(env);
+ if (ctx.size != ctx_size) {
+ return enif_make_badarg(env);
}
- hmac_md5(key.data, key.size, data.data, data.size, hmacbuf);
- memcpy(enif_make_new_binary(env, mac_sz, &ret), hmacbuf, mac_sz);
- CONSUME_REDS(env,data);
- return ret;
-}
-static ERL_NIF_TERM sha_mac_n(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key, Data, MacSize) */
- unsigned char hmacbuf[SHA_DIGEST_LENGTH];
- ErlNifBinary key, data;
- unsigned mac_sz;
- ERL_NIF_TERM ret;
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
- || !enif_inspect_iolist_as_binary(env, argv[1], &data)
- || !enif_get_uint(env,argv[2],&mac_sz) || mac_sz > SHA_LEN) {
- return enif_make_badarg(env);
- }
- hmac_sha1(key.data, key.size, data.data, data.size, hmacbuf);
- memcpy(enif_make_new_binary(env, mac_sz, &ret),
- hmacbuf, mac_sz);
- CONSUME_REDS(env,data);
- return ret;
-}
+ new_ctx = enif_alloc(ctx_size);
+ memcpy(new_ctx, ctx.data, ctx_size);
+ ctx_final(enif_make_new_binary(env, (size_t)EVP_MD_size(md), &ret),
+ new_ctx);
+ enif_free(new_ctx);
-static ERL_NIF_TERM sha224_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key, Data, MacSize) */
-#ifdef HAVE_SHA224
- unsigned char hmacbuf[SHA224_DIGEST_LENGTH];
- ErlNifBinary key, data;
- unsigned mac_sz;
- ERL_NIF_TERM ret;
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
- || !enif_inspect_iolist_as_binary(env, argv[1], &data)
- || !enif_get_uint(env,argv[2],&mac_sz) || mac_sz > SHA224_DIGEST_LENGTH) {
- return enif_make_badarg(env);
- }
- hmac_sha224(key.data, key.size, data.data, data.size, hmacbuf);
- memcpy(enif_make_new_binary(env, mac_sz, &ret),
- hmacbuf, mac_sz);
- CONSUME_REDS(env,data);
return ret;
-#else
- return atom_notsup;
-#endif
}
+#endif /* OPENSSL_VERSION_NUMBER < 1.0 */
-static ERL_NIF_TERM sha256_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key, Data, MacSize) */
-#ifdef HAVE_SHA256
- unsigned char hmacbuf[SHA256_DIGEST_LENGTH];
- ErlNifBinary key, data;
- unsigned mac_sz;
- ERL_NIF_TERM ret;
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
- || !enif_inspect_iolist_as_binary(env, argv[1], &data)
- || !enif_get_uint(env,argv[2],&mac_sz) || mac_sz > SHA256_DIGEST_LENGTH) {
- return enif_make_badarg(env);
- }
- hmac_sha256(key.data, key.size, data.data, data.size, hmacbuf);
- memcpy(enif_make_new_binary(env, mac_sz, &ret),
- hmacbuf, mac_sz);
- CONSUME_REDS(env,data);
- return ret;
-#else
- return atom_notsup;
-#endif
-}
+static ERL_NIF_TERM hmac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Type, Key, Data) or (Type, Key, Data, MacSize) */
+ struct digest_type_t *digp = NULL;
+ ErlNifBinary key, data;
+ unsigned char buff[EVP_MAX_MD_SIZE];
+ unsigned size = 0, req_size = 0;
+ ERL_NIF_TERM ret;
-static ERL_NIF_TERM sha384_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key, Data, MacSize) */
-#ifdef HAVE_SHA384
- unsigned char hmacbuf[SHA384_DIGEST_LENGTH];
- ErlNifBinary key, data;
- unsigned mac_sz;
- ERL_NIF_TERM ret;
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
- || !enif_inspect_iolist_as_binary(env, argv[1], &data)
- || !enif_get_uint(env,argv[2],&mac_sz) || mac_sz > SHA384_DIGEST_LENGTH) {
- return enif_make_badarg(env);
+ digp = get_digest_type(argv[0]);
+ if (!digp ||
+ !enif_inspect_iolist_as_binary(env, argv[1], &key) ||
+ !enif_inspect_iolist_as_binary(env, argv[2], &data) ||
+ (argc == 4 && !enif_get_uint(env, argv[3], &req_size))) {
+ return enif_make_badarg(env);
}
- hmac_sha384(key.data, key.size, data.data, data.size, hmacbuf);
- memcpy(enif_make_new_binary(env, mac_sz, &ret),
- hmacbuf, mac_sz);
- CONSUME_REDS(env,data);
- return ret;
-#else
- return atom_notsup;
-#endif
-}
+ if (!digp->md_func ||
+ !HMAC(digp->md_func(),
+ key.data, key.size,
+ data.data, data.size,
+ buff, &size)) {
+ return atom_notsup;
+ }
+ ASSERT(0 < size && size <= EVP_MAX_MD_SIZE);
+ CONSUME_REDS(env, data);
-static ERL_NIF_TERM sha512_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key, Data, MacSize) */
-#ifdef HAVE_SHA512
- unsigned char hmacbuf[SHA512_DIGEST_LENGTH];
- ErlNifBinary key, data;
- unsigned mac_sz;
- ERL_NIF_TERM ret;
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
- || !enif_inspect_iolist_as_binary(env, argv[1], &data)
- || !enif_get_uint(env,argv[2],&mac_sz) || mac_sz > SHA512_DIGEST_LENGTH) {
- return enif_make_badarg(env);
+ if (argc == 4) {
+ if (req_size <= size) {
+ size = req_size;
+ }
+ else {
+ return enif_make_badarg(env);
+ }
}
- hmac_sha512(key.data, key.size, data.data, data.size, hmacbuf);
- memcpy(enif_make_new_binary(env, mac_sz, &ret),
- hmacbuf, mac_sz);
- CONSUME_REDS(env,data);
+ memcpy(enif_make_new_binary(env, size, &ret), buff, size);
return ret;
-#else
- return atom_notsup;
-#endif
}
static void hmac_context_dtor(ErlNifEnv* env, struct hmac_context *obj)
@@ -1374,53 +1212,46 @@ static void hmac_context_dtor(ErlNifEnv* env, struct hmac_context *obj)
enif_mutex_destroy(obj->mtx);
}
-static ERL_NIF_TERM hmac_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+static ERL_NIF_TERM hmac_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Type, Key) */
- ErlNifBinary key;
- struct hmac_context* obj;
- const EVP_MD *md;
- ERL_NIF_TERM ret;
-
+ struct digest_type_t *digp = NULL;
+ ErlNifBinary key;
+ ERL_NIF_TERM ret;
+ struct hmac_context *obj;
- if (argv[0] == atom_sha) md = EVP_sha1();
-#ifdef HAVE_SHA224
- else if (argv[0] == atom_sha224) md = EVP_sha224();
-#endif
-#ifdef HAVE_SHA256
- else if (argv[0] == atom_sha256) md = EVP_sha256();
-#endif
-#ifdef HAVE_SHA384
- else if (argv[0] == atom_sha384) md = EVP_sha384();
-#endif
-#ifdef HAVE_SHA512
- else if (argv[0] == atom_sha512) md = EVP_sha512();
-#endif
- else if (argv[0] == atom_md5) md = EVP_md5();
- else if (argv[0] == atom_ripemd160) md = EVP_ripemd160();
- else goto badarg;
-
- if (!enif_inspect_iolist_as_binary(env, argv[1], &key)) {
- badarg:
- return enif_make_badarg(env);
+ digp = get_digest_type(argv[0]);
+ if (!digp ||
+ !enif_inspect_iolist_as_binary(env, argv[1], &key)) {
+ return enif_make_badarg(env);
+ }
+ if (!digp->md_func) {
+ return atom_notsup;
}
obj = enif_alloc_resource(hmac_context_rtype, sizeof(struct hmac_context));
obj->mtx = enif_mutex_create("crypto.hmac");
obj->alive = 1;
- HMAC_CTX_init(&obj->ctx);
- HMAC_Init(&obj->ctx, key.data, key.size, md);
+#if OPENSSL_VERSION_NUMBER >= 0x1000000fL
+ // Check the return value of HMAC_Init: it may fail in FIPS mode
+ // for disabled algorithms
+ if (!HMAC_Init(&obj->ctx, key.data, key.size, digp->md_func())) {
+ enif_release_resource(obj);
+ return atom_notsup;
+ }
+#else
+ HMAC_Init(&obj->ctx, key.data, key.size, digp->md_func());
+#endif
ret = enif_make_resource(env, obj);
enif_release_resource(obj);
return ret;
}
-static ERL_NIF_TERM hmac_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+static ERL_NIF_TERM hmac_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Context, Data) */
ErlNifBinary data;
struct hmac_context* obj;
-
if (!enif_get_resource(env, argv[0], hmac_context_rtype, (void**)&obj)
|| !enif_inspect_iolist_as_binary(env, argv[1], &data)) {
return enif_make_badarg(env);
@@ -1437,7 +1268,7 @@ static ERL_NIF_TERM hmac_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg
return argv[0];
}
-static ERL_NIF_TERM hmac_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+static ERL_NIF_TERM hmac_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Context) or (Context, HashLen) */
ERL_NIF_TERM ret;
struct hmac_context* obj;
@@ -1446,7 +1277,6 @@ static ERL_NIF_TERM hmac_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
unsigned int req_len = 0;
unsigned int mac_len;
-
if (!enif_get_resource(env,argv[0],hmac_context_rtype, (void**)&obj)
|| (argc == 2 && !enif_get_uint(env, argv[1], &req_len))) {
return enif_make_badarg(env);
@@ -1473,199 +1303,196 @@ static ERL_NIF_TERM hmac_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
return ret;
}
-static ERL_NIF_TERM des_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key, Ivec, Text, IsEncrypt) */
- ErlNifBinary key, ivec, text;
- DES_key_schedule schedule;
- DES_cblock ivec_clone; /* writable copy */
- ERL_NIF_TERM ret;
-
+static ERL_NIF_TERM block_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Type, Key, Ivec, Text, IsEncrypt) or (Type, Key, Text, IsEncrypt) */
+ struct cipher_type_t *cipherp = NULL;
+ const EVP_CIPHER *cipher;
+ ErlNifBinary key, ivec, text;
+ EVP_CIPHER_CTX ctx;
+ ERL_NIF_TERM ret;
+ unsigned char *out;
+ int ivec_size, out_size = 0;
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || key.size != 8
- || !enif_inspect_binary(env, argv[1], &ivec) || ivec.size != 8
- || !enif_inspect_iolist_as_binary(env, argv[2], &text)
- || text.size % 8 != 0) {
- return enif_make_badarg(env);
+ if (!enif_inspect_iolist_as_binary(env, argv[1], &key)
+ || !(cipherp = get_cipher_type(argv[0], key.size))
+ || !enif_inspect_iolist_as_binary(env, argv[argc - 2], &text)) {
+ return enif_make_badarg(env);
}
- memcpy(&ivec_clone, ivec.data, 8);
- DES_set_key((const_DES_cblock*)key.data, &schedule);
- DES_ncbc_encrypt(text.data, enif_make_new_binary(env, text.size, &ret),
- text.size, &schedule, &ivec_clone, (argv[3] == atom_true));
- CONSUME_REDS(env,text);
- return ret;
-}
-
-static ERL_NIF_TERM des_cfb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key, Ivec, Text, IsEncrypt) */
- ErlNifBinary key, ivec, text;
- DES_key_schedule schedule;
- DES_cblock ivec_clone; /* writable copy */
- ERL_NIF_TERM ret;
-
-
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || key.size != 8
- || !enif_inspect_binary(env, argv[1], &ivec) || ivec.size != 8
- || !enif_inspect_iolist_as_binary(env, argv[2], &text)) {
- return enif_make_badarg(env);
+ if (!cipherp->cipher_func) {
+ return enif_raise_exception(env, atom_notsup);
}
- memcpy(&ivec_clone, ivec.data, 8);
- DES_set_key((const_DES_cblock*)key.data, &schedule);
- DES_cfb_encrypt(text.data, enif_make_new_binary(env, text.size, &ret),
- 8, text.size, &schedule, &ivec_clone, (argv[3] == atom_true));
- CONSUME_REDS(env,text);
- return ret;
-}
-static ERL_NIF_TERM des_ecb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key, Text/Cipher, IsEncrypt) */
- ErlNifBinary key, text;
- DES_key_schedule schedule;
- ERL_NIF_TERM ret;
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || key.size != 8 ||
- !enif_inspect_iolist_as_binary(env, argv[1], &text) || text.size != 8) {
- return enif_make_badarg(env);
+ if ((argv[0] == atom_aes_cfb8 || argv[0] == atom_aes_cfb128)
+ && (key.size == 24 || key.size == 32)) {
+ /* Why do EVP_CIPHER_CTX_set_key_length() fail on these key sizes?
+ * Fall back on low level API
+ */
+ return aes_cfb_8_crypt(env, argc-1, argv+1);
}
- DES_set_key((const_DES_cblock*)key.data, &schedule);
- DES_ecb_encrypt((const_DES_cblock*)text.data,
- (DES_cblock*)enif_make_new_binary(env, 8, &ret),
- &schedule, (argv[2] == atom_true));
- CONSUME_REDS(env,text);
- return ret;
-}
-static ERL_NIF_TERM des_ede3_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key1, Key2, Key3, IVec, Text/Cipher, IsEncrypt) */
- ErlNifBinary key1, key2, key3, ivec, text;
- DES_key_schedule schedule1, schedule2, schedule3;
- DES_cblock ivec_clone; /* writable copy */
- ERL_NIF_TERM ret;
+ cipher = cipherp->cipher_func();
+ ivec_size = EVP_CIPHER_iv_length(cipher);
+#ifdef HAVE_ECB_IVEC_BUG
+ if (argv[0] == atom_aes_ecb || argv[0] == atom_blowfish_ecb ||
+ argv[0] == atom_des_ecb)
+ ivec_size = 0; /* 0.9.8l returns faulty ivec_size */
+#endif
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key1) || key1.size != 8
- || !enif_inspect_iolist_as_binary(env, argv[1], &key2) || key2.size != 8
- || !enif_inspect_iolist_as_binary(env, argv[2], &key3) || key3.size != 8
- || !enif_inspect_binary(env, argv[3], &ivec) || ivec.size != 8
- || !enif_inspect_iolist_as_binary(env, argv[4], &text)
- || text.size % 8 != 0) {
- return enif_make_badarg(env);
+ if (text.size % EVP_CIPHER_block_size(cipher) != 0 ||
+ (ivec_size == 0 ? argc != 4
+ : (argc != 5 ||
+ !enif_inspect_iolist_as_binary(env, argv[2], &ivec) ||
+ ivec.size != ivec_size))) {
+ return enif_make_badarg(env);
}
- memcpy(&ivec_clone, ivec.data, 8);
- DES_set_key((const_DES_cblock*)key1.data, &schedule1);
- DES_set_key((const_DES_cblock*)key2.data, &schedule2);
- DES_set_key((const_DES_cblock*)key3.data, &schedule3);
- DES_ede3_cbc_encrypt(text.data, enif_make_new_binary(env,text.size,&ret),
- text.size, &schedule1, &schedule2, &schedule3,
- &ivec_clone, (argv[5] == atom_true));
- CONSUME_REDS(env,text);
- return ret;
-}
+ out = enif_make_new_binary(env, text.size, &ret);
-static ERL_NIF_TERM des_ede3_cfb_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key1, Key2, Key3, IVec, Text/Cipher, IsEncrypt) */
-#ifdef HAVE_DES_ede3_cfb_encrypt
- ErlNifBinary key1, key2, key3, ivec, text;
- DES_key_schedule schedule1, schedule2, schedule3;
- DES_cblock ivec_clone; /* writable copy */
- ERL_NIF_TERM ret;
+ EVP_CIPHER_CTX_init(&ctx);
+ if (!EVP_CipherInit_ex(&ctx, cipher, NULL, NULL, NULL,
+ (argv[argc - 1] == atom_true)) ||
+ !EVP_CIPHER_CTX_set_key_length(&ctx, key.size) ||
+ !(EVP_CIPHER_type(cipher) != NID_rc2_cbc ||
+ EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_SET_RC2_KEY_BITS, key.size * 8, NULL)) ||
+ !EVP_CipherInit_ex(&ctx, NULL, NULL,
+ key.data, ivec_size ? ivec.data : NULL, -1) ||
+ !EVP_CIPHER_CTX_set_padding(&ctx, 0)) {
+ return enif_raise_exception(env, atom_notsup);
+ }
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key1) || key1.size != 8
- || !enif_inspect_iolist_as_binary(env, argv[1], &key2) || key2.size != 8
- || !enif_inspect_iolist_as_binary(env, argv[2], &key3) || key3.size != 8
- || !enif_inspect_binary(env, argv[3], &ivec) || ivec.size != 8
- || !enif_inspect_iolist_as_binary(env, argv[4], &text)) {
- return enif_make_badarg(env);
+ if (text.size > 0 && /* OpenSSL 0.9.8h asserts text.size > 0 */
+ (!EVP_CipherUpdate(&ctx, out, &out_size, text.data, text.size)
+ || (ASSERT(out_size == text.size), 0)
+ || !EVP_CipherFinal_ex(&ctx, out + out_size, &out_size))) {
+
+ EVP_CIPHER_CTX_cleanup(&ctx);
+ return enif_raise_exception(env, atom_notsup);
}
+ ASSERT(out_size == 0);
+ EVP_CIPHER_CTX_cleanup(&ctx);
+ CONSUME_REDS(env, text);
- memcpy(&ivec_clone, ivec.data, 8);
- DES_set_key((const_DES_cblock*)key1.data, &schedule1);
- DES_set_key((const_DES_cblock*)key2.data, &schedule2);
- DES_set_key((const_DES_cblock*)key3.data, &schedule3);
- DES_ede3_cfb_encrypt(text.data, enif_make_new_binary(env,text.size,&ret),
- 8, text.size, &schedule1, &schedule2, &schedule3,
- &ivec_clone, (argv[5] == atom_true));
- CONSUME_REDS(env,text);
return ret;
-#else
- return atom_notsup;
-#endif
}
static ERL_NIF_TERM aes_cfb_8_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key, IVec, Data, IsEncrypt) */
- ErlNifBinary key, ivec, text;
- AES_KEY aes_key;
- unsigned char ivec_clone[16]; /* writable copy */
- int new_ivlen = 0;
- ERL_NIF_TERM ret;
-
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
- || !(key.size == 16 || key.size == 24 || key.size == 32)
- || !enif_inspect_binary(env, argv[1], &ivec) || ivec.size != 16
- || !enif_inspect_iolist_as_binary(env, argv[2], &text)) {
- return enif_make_badarg(env);
- }
-
- memcpy(ivec_clone, ivec.data, 16);
- AES_set_encrypt_key(key.data, key.size * 8, &aes_key);
- AES_cfb8_encrypt((unsigned char *) text.data,
- enif_make_new_binary(env, text.size, &ret),
- text.size, &aes_key, ivec_clone, &new_ivlen,
- (argv[3] == atom_true));
- CONSUME_REDS(env,text);
- return ret;
+{/* (Key, IVec, Data, IsEncrypt) */
+ ErlNifBinary key, ivec, text;
+ AES_KEY aes_key;
+ unsigned char ivec_clone[16]; /* writable copy */
+ int new_ivlen = 0;
+ ERL_NIF_TERM ret;
+
+ if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
+ || !(key.size == 16 || key.size == 24 || key.size == 32)
+ || !enif_inspect_binary(env, argv[1], &ivec) || ivec.size != 16
+ || !enif_inspect_iolist_as_binary(env, argv[2], &text)) {
+ return enif_make_badarg(env);
+ }
+
+ memcpy(ivec_clone, ivec.data, 16);
+ AES_set_encrypt_key(key.data, key.size * 8, &aes_key);
+ AES_cfb8_encrypt((unsigned char *) text.data,
+ enif_make_new_binary(env, text.size, &ret),
+ text.size, &aes_key, ivec_clone, &new_ivlen,
+ (argv[3] == atom_true));
+ CONSUME_REDS(env,text);
+ return ret;
}
-static ERL_NIF_TERM aes_cfb_128_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key, IVec, Data, IsEncrypt) */
- ErlNifBinary key, ivec, text;
+static ERL_NIF_TERM aes_ige_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Key, IVec, Data, IsEncrypt) */
+#ifdef HAVE_AES_IGE
+ ErlNifBinary key_bin, ivec_bin, data_bin;
AES_KEY aes_key;
- unsigned char ivec_clone[16]; /* writable copy */
- int new_ivlen = 0;
+ unsigned char ivec[32];
+ int i;
+ unsigned char* ret_ptr;
ERL_NIF_TERM ret;
+ if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin)
+ || (key_bin.size != 16 && key_bin.size != 32)
+ || !enif_inspect_binary(env, argv[1], &ivec_bin)
+ || ivec_bin.size != 32
+ || !enif_inspect_iolist_as_binary(env, argv[2], &data_bin)
+ || data_bin.size % 16 != 0) {
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
- || !(key.size == 16 || key.size == 24 || key.size == 32)
- || !enif_inspect_binary(env, argv[1], &ivec) || ivec.size != 16
- || !enif_inspect_iolist_as_binary(env, argv[2], &text)) {
- return enif_make_badarg(env);
+ return enif_make_badarg(env);
}
- memcpy(ivec_clone, ivec.data, 16);
- AES_set_encrypt_key(key.data, key.size * 8, &aes_key);
- AES_cfb128_encrypt((unsigned char *) text.data,
- enif_make_new_binary(env, text.size, &ret),
- text.size, &aes_key, ivec_clone, &new_ivlen,
- (argv[3] == atom_true));
- CONSUME_REDS(env,text);
+ if (argv[3] == atom_true) {
+ i = AES_ENCRYPT;
+ AES_set_encrypt_key(key_bin.data, key_bin.size*8, &aes_key);
+ }
+ else {
+ i = AES_DECRYPT;
+ AES_set_decrypt_key(key_bin.data, key_bin.size*8, &aes_key);
+ }
+
+ ret_ptr = enif_make_new_binary(env, data_bin.size, &ret);
+ memcpy(ivec, ivec_bin.data, 32); /* writable copy */
+ AES_ige_encrypt(data_bin.data, ret_ptr, data_bin.size, &aes_key, ivec, i);
+ CONSUME_REDS(env,data_bin);
return ret;
+#else
+ return atom_notsup;
+#endif
}
/* Common for both encrypt and decrypt
*/
static ERL_NIF_TERM aes_ctr_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Key, IVec, Data) */
- ErlNifBinary key, ivec, text;
- AES_KEY aes_key;
- unsigned char ivec_clone[16]; /* writable copy */
- unsigned char ecount_buf[AES_BLOCK_SIZE];
- unsigned int num = 0;
- ERL_NIF_TERM ret;
-
+ ErlNifBinary key, ivec, text;
+#ifdef HAVE_EVP_AES_CTR
+ const EVP_CIPHER *cipher;
+ EVP_CIPHER_CTX ctx;
+ unsigned char *out;
+ int outl = 0;
+#else
+ AES_KEY aes_key;
+ unsigned char ivec_clone[16]; /* writable copy */
+ unsigned char ecount_buf[AES_BLOCK_SIZE];
+ unsigned int num = 0;
+#endif
+ ERL_NIF_TERM ret;
if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
+#ifndef HAVE_EVP_AES_CTR
|| AES_set_encrypt_key(key.data, key.size*8, &aes_key) != 0
+#endif
|| !enif_inspect_binary(env, argv[1], &ivec) || ivec.size != 16
|| !enif_inspect_iolist_as_binary(env, argv[2], &text)) {
return enif_make_badarg(env);
}
+#ifdef HAVE_EVP_AES_CTR
+ switch (key.size)
+ {
+ case 16: cipher = EVP_aes_128_ctr(); break;
+ case 24: cipher = EVP_aes_192_ctr(); break;
+ case 32: cipher = EVP_aes_256_ctr(); break;
+ default: return enif_make_badarg(env);
+ }
+
+ out = enif_make_new_binary(env,text.size,&ret);
+ EVP_CIPHER_CTX_init(&ctx);
+ EVP_CipherInit_ex(&ctx, cipher, NULL,
+ key.data, ivec.data, (argv[3] == atom_true));
+ EVP_CIPHER_CTX_set_padding(&ctx, 0);
+ EVP_CipherUpdate(&ctx, out, &outl, text.data, text.size);
+ ASSERT(outl == text.size);
+ EVP_CipherFinal_ex(&ctx, out + outl, &outl);
+ ASSERT(outl == 0);
+ EVP_CIPHER_CTX_cleanup(&ctx);
+#else
memcpy(ivec_clone, ivec.data, 16);
memset(ecount_buf, 0, sizeof(ecount_buf));
AES_ctr128_encrypt((unsigned char *) text.data,
enif_make_new_binary(env, text.size, &ret),
text.size, &aes_key, ivec_clone, ecount_buf, &num);
+#endif
CONSUME_REDS(env,text);
/* To do an incremental {en|de}cryption, the state to to keep between calls
@@ -1675,6 +1502,81 @@ static ERL_NIF_TERM aes_ctr_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM
/* Initializes state for ctr streaming (de)encryption
*/
+#ifdef HAVE_EVP_AES_CTR
+static ERL_NIF_TERM aes_ctr_stream_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Key, IVec) */
+ ErlNifBinary key_bin, ivec_bin;
+ EVP_CIPHER_CTX *ctx;
+ const EVP_CIPHER *cipher;
+ ERL_NIF_TERM ret;
+
+ if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin)
+ || !enif_inspect_binary(env, argv[1], &ivec_bin)
+ || ivec_bin.size != 16) {
+ return enif_make_badarg(env);
+ }
+
+ switch (key_bin.size)
+ {
+ case 16: cipher = EVP_aes_128_ctr(); break;
+ case 24: cipher = EVP_aes_192_ctr(); break;
+ case 32: cipher = EVP_aes_256_ctr(); break;
+ default: return enif_make_badarg(env);
+ }
+
+ ctx = enif_alloc_resource(evp_cipher_ctx_rtype, sizeof(EVP_CIPHER_CTX));
+ EVP_CIPHER_CTX_init(ctx);
+ EVP_CipherInit_ex(ctx, cipher, NULL,
+ key_bin.data, ivec_bin.data, 1);
+ EVP_CIPHER_CTX_set_padding(ctx, 0);
+ ret = enif_make_resource(env, ctx);
+ enif_release_resource(ctx);
+ return ret;
+}
+static ERL_NIF_TERM aes_ctr_stream_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Context, Data) */
+ EVP_CIPHER_CTX *ctx, *new_ctx;
+ ErlNifBinary data_bin;
+ ERL_NIF_TERM ret, cipher_term;
+ unsigned char *out;
+ int outl = 0;
+
+ if (!enif_get_resource(env, argv[0], evp_cipher_ctx_rtype, (void**)&ctx)
+ || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) {
+ return enif_make_badarg(env);
+ }
+ new_ctx = enif_alloc_resource(evp_cipher_ctx_rtype, sizeof(EVP_CIPHER_CTX));
+ EVP_CIPHER_CTX_init(new_ctx);
+ EVP_CIPHER_CTX_copy(new_ctx, ctx);
+ out = enif_make_new_binary(env, data_bin.size, &cipher_term);
+ EVP_CipherUpdate(new_ctx, out, &outl, data_bin.data, data_bin.size);
+ ASSERT(outl == data_bin.size);
+
+ ret = enif_make_tuple2(env, enif_make_resource(env, new_ctx), cipher_term);
+ enif_release_resource(new_ctx);
+ CONSUME_REDS(env,data_bin);
+ return ret;
+}
+
+#else /* if not HAVE_EVP_AES_CTR */
+
+static ERL_NIF_TERM aes_ctr_stream_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Key, IVec) */
+ ErlNifBinary key_bin, ivec_bin;
+ ERL_NIF_TERM ecount_bin;
+
+ if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin)
+ || !enif_inspect_binary(env, argv[1], &ivec_bin)
+ || !(key_bin.size == 16 || key_bin.size == 24 || key_bin.size ==32)
+ || ivec_bin.size != 16) {
+ return enif_make_badarg(env);
+ }
+
+ memset(enif_make_new_binary(env, AES_BLOCK_SIZE, &ecount_bin),
+ 0, AES_BLOCK_SIZE);
+ return enif_make_tuple4(env, argv[0], argv[1], ecount_bin, enif_make_int(env, 0));
+}
+
static ERL_NIF_TERM aes_ctr_stream_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* ({Key, IVec, ECount, Num}, Data) */
ErlNifBinary key_bin, ivec_bin, text_bin, ecount_bin;
@@ -1686,7 +1588,6 @@ static ERL_NIF_TERM aes_ctr_stream_encrypt(ErlNifEnv* env, int argc, const ERL_N
unsigned char * ivec2_buf;
unsigned char * ecount2_buf;
-
if (!enif_get_tuple(env, argv[0], &state_arity, &state_term)
|| state_arity != 4
|| !enif_inspect_iolist_as_binary(env, state_term[0], &key_bin)
@@ -1714,6 +1615,7 @@ static ERL_NIF_TERM aes_ctr_stream_encrypt(ErlNifEnv* env, int argc, const ERL_N
CONSUME_REDS(env,text_bin);
return ret;
}
+#endif /* !HAVE_EVP_AES_CTR */
static ERL_NIF_TERM aes_gcm_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Key,Iv,AAD,In) */
@@ -1724,7 +1626,6 @@ static ERL_NIF_TERM aes_gcm_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM
unsigned char *outp;
ERL_NIF_TERM out, out_tag;
-
if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
|| AES_set_encrypt_key(key.data, key.size*8, &aes_key) != 0
|| !enif_inspect_binary(env, argv[1], &iv) || iv.size == 0
@@ -1760,7 +1661,7 @@ out_err:
return atom_error;
#else
- return atom_notsup;
+ return enif_raise_exception(env, atom_notsup);
#endif
}
@@ -1773,7 +1674,6 @@ static ERL_NIF_TERM aes_gcm_decrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM
unsigned char *outp;
ERL_NIF_TERM out;
-
if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
|| AES_set_encrypt_key(key.data, key.size*8, &aes_key) != 0
|| !enif_inspect_binary(env, argv[1], &iv) || iv.size == 0
@@ -1810,7 +1710,7 @@ out_err:
CRYPTO_gcm128_release(ctx);
return atom_error;
#else
- return atom_notsup;
+ return enif_raise_exception(env, atom_notsup);
#endif
}
@@ -1843,7 +1743,6 @@ static ERL_NIF_TERM chacha20_poly1305_encrypt(ErlNifEnv* env, int argc, const ER
unsigned char poly1305_key[32];
poly1305_state poly1305;
-
if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || key.size != 32
|| !enif_inspect_binary(env, argv[1], &iv) || iv.size != CHACHA20_NONCE_LEN
|| !enif_inspect_iolist_as_binary(env, argv[2], &aad)
@@ -1881,7 +1780,7 @@ static ERL_NIF_TERM chacha20_poly1305_encrypt(ErlNifEnv* env, int argc, const ER
return enif_make_tuple2(env, out, out_tag);
#else
- return atom_notsup;
+ return enif_raise_exception(env, atom_notsup);
#endif
}
@@ -1896,7 +1795,6 @@ static ERL_NIF_TERM chacha20_poly1305_decrypt(ErlNifEnv* env, int argc, const ER
unsigned char mac[POLY1305_TAG_LEN];
poly1305_state poly1305;
-
if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || key.size != 32
|| !enif_inspect_binary(env, argv[1], &iv) || iv.size != CHACHA20_NONCE_LEN
|| !enif_inspect_iolist_as_binary(env, argv[2], &aad)
@@ -1937,46 +1835,16 @@ static ERL_NIF_TERM chacha20_poly1305_decrypt(ErlNifEnv* env, int argc, const ER
return out;
#else
- return atom_notsup;
+ return enif_raise_exception(env, atom_notsup);
#endif
}
-static ERL_NIF_TERM aes_ecb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key, Data, IsEncrypt) */
- ErlNifBinary key_bin, data_bin;
- AES_KEY aes_key;
- int i;
- unsigned char* ret_ptr;
- ERL_NIF_TERM ret;
-
-
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin)
- || (key_bin.size != 16 && key_bin.size != 32)
- || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)
- || data_bin.size % 16 != 0) {
- return enif_make_badarg(env);
- }
-
- if (argv[2] == atom_true) {
- i = AES_ENCRYPT;
- AES_set_encrypt_key(key_bin.data, key_bin.size*8, &aes_key);
- }
- else {
- i = AES_DECRYPT;
- AES_set_decrypt_key(key_bin.data, key_bin.size*8, &aes_key);
- }
-
- ret_ptr = enif_make_new_binary(env, data_bin.size, &ret);
- AES_ecb_encrypt(data_bin.data, ret_ptr, &aes_key, i);
- CONSUME_REDS(env,data_bin);
- return ret;
-}
-
static ERL_NIF_TERM rand_bytes_1(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Bytes) */
unsigned bytes;
unsigned char* data;
ERL_NIF_TERM ret;
+
if (!enif_get_uint(env, argv[0], &bytes)) {
return enif_make_badarg(env);
}
@@ -1990,6 +1858,7 @@ static ERL_NIF_TERM strong_rand_bytes_nif(ErlNifEnv* env, int argc, const ERL_NI
unsigned bytes;
unsigned char* data;
ERL_NIF_TERM ret;
+
if (!enif_get_uint(env, argv[0], &bytes)) {
return enif_make_badarg(env);
}
@@ -2007,6 +1876,7 @@ static ERL_NIF_TERM rand_bytes_3(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
unsigned char* data;
unsigned top_mask, bot_mask;
ERL_NIF_TERM ret;
+
if (!enif_get_uint(env, argv[0], &bytes)
|| !enif_get_uint(env, argv[1], &top_mask)
|| !enif_get_uint(env, argv[2], &bot_mask)) {
@@ -2030,7 +1900,6 @@ static ERL_NIF_TERM strong_rand_mpint_nif(ErlNifEnv* env, int argc, const ERL_NI
unsigned dlen;
ERL_NIF_TERM ret;
-
if (!enif_get_uint(env, argv[0], &bits)
|| !enif_get_int(env, argv[1], &top)
|| !enif_get_int(env, argv[2], &bottom)) {
@@ -2099,7 +1968,6 @@ static ERL_NIF_TERM rand_uniform_nif(ErlNifEnv* env, int argc, const ERL_NIF_TER
unsigned dlen;
ERL_NIF_TERM ret;
-
if (!get_bn_from_mpint(env, argv[0], &bn_from)
|| !get_bn_from_mpint(env, argv[1], &bn_rand)) {
if (bn_from) BN_free(bn_from);
@@ -2131,7 +1999,6 @@ static ERL_NIF_TERM mod_exp_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg
unsigned extra_byte;
ERL_NIF_TERM ret;
-
if (!get_bn_from_bin(env, argv[0], &bn_base)
|| !get_bn_from_bin(env, argv[1], &bn_exponent)
|| !get_bn_from_bin(env, argv[2], &bn_modulo)
@@ -2163,45 +2030,17 @@ static ERL_NIF_TERM mod_exp_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg
}
static ERL_NIF_TERM dss_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (DigestType|none, Data|{digest,Digest}, Signature,Key=[P, Q, G, Y]) */
- ErlNifBinary data_bin, sign_bin;
+{/* (sha, Digest, Signature,Key=[P, Q, G, Y]) */
+ ErlNifBinary digest_bin, sign_bin;
BIGNUM *dsa_p = NULL, *dsa_q = NULL, *dsa_g = NULL, *dsa_y = NULL;
- unsigned char hmacbuf[SHA_DIGEST_LENGTH];
- unsigned char* digest;
ERL_NIF_TERM head, tail;
- const ERL_NIF_TERM* tpl_terms;
- int tpl_arity;
DSA *dsa;
int i;
-
- if (argv[0] == atom_sha) {
- if (enif_get_tuple(env, argv[1], &tpl_arity, &tpl_terms)) {
- if (tpl_arity != 2 || tpl_terms[0] != atom_digest
- || !enif_inspect_binary(env, tpl_terms[1], &data_bin)
- || data_bin.size != SHA_DIGEST_LENGTH) {
-
- return enif_make_badarg(env);
- }
- digest = data_bin.data;
- }
- else {
- if (!enif_inspect_binary(env, argv[1], &data_bin)) {
- return enif_make_badarg(env);
- }
- SHA1(data_bin.data, data_bin.size, hmacbuf);
- digest = hmacbuf;
- }
- }
- else if (argv[0] == atom_none && enif_inspect_binary(env, argv[1], &data_bin)
- && data_bin.size == SHA_DIGEST_LENGTH) {
- digest = data_bin.data;
- }
- else {
- return enif_make_badarg(env);
- }
-
- if (!enif_inspect_binary(env, argv[2], &sign_bin)
+ if (!argv[0] == atom_sha
+ || !enif_inspect_binary(env, argv[1], &digest_bin)
+ || digest_bin.size != SHA_DIGEST_LENGTH
+ || !enif_inspect_binary(env, argv[2], &sign_bin)
|| !enif_get_list_cell(env, argv[3], &head, &tail)
|| !get_bn_from_bin(env, head, &dsa_p)
|| !enif_get_list_cell(env, tail, &head, &tail)
@@ -2225,94 +2064,27 @@ static ERL_NIF_TERM dss_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM
dsa->g = dsa_g;
dsa->priv_key = NULL;
dsa->pub_key = dsa_y;
- i = DSA_verify(0, digest, SHA_DIGEST_LENGTH,
+ i = DSA_verify(0, digest_bin.data, SHA_DIGEST_LENGTH,
sign_bin.data, sign_bin.size, dsa);
DSA_free(dsa);
return(i > 0) ? atom_true : atom_false;
}
-
-static void md5_digest(unsigned char* in, unsigned int in_len, unsigned char* out)
-{
- MD5(in, in_len, out);
-}
-static void sha1_digest(unsigned char* in, unsigned int in_len, unsigned char* out)
-{
- SHA1(in, in_len, out);
-}
-#ifdef HAVE_SHA224
-static void sha224_digest(unsigned char* in, unsigned int in_len, unsigned char* out)
-{
- SHA224(in, in_len, out);
-}
-#endif
-#ifdef HAVE_SHA256
-static void sha256_digest(unsigned char* in, unsigned int in_len, unsigned char* out)
-{
- SHA256(in, in_len, out);
-}
-#endif
-#ifdef HAVE_SHA384
-static void sha384_digest(unsigned char* in, unsigned int in_len, unsigned char* out)
-{
- SHA384(in, in_len, out);
-}
-#endif
-#ifdef HAVE_SHA512
-static void sha512_digest(unsigned char* in, unsigned int in_len, unsigned char* out)
+static void init_digest_types(ErlNifEnv* env)
{
- SHA512(in, in_len, out);
-}
-#endif
+ struct digest_type_t* p = digest_types;
-struct digest_type_t {
- const char* type_str;
- unsigned len; /* 0 if notsup */
- int NID_type;
- void (*funcp)(unsigned char* in, unsigned int in_len, unsigned char* out);
- ERL_NIF_TERM type_atom;
-};
+ for (p = digest_types; p->type_str; p++) {
+ p->type_atom = enif_make_atom(env, p->type_str);
+ }
-struct digest_type_t digest_types[] =
-{
- {"md5", MD5_DIGEST_LENGTH, NID_md5, md5_digest},
- {"sha", SHA_DIGEST_LENGTH, NID_sha1, sha1_digest},
- {"sha224",
-#ifdef HAVE_SHA224
- SHA224_LEN, NID_sha224, sha224_digest
-#else
- 0
-#endif
- },
- {"sha256",
-#ifdef HAVE_SHA256
- SHA256_LEN, NID_sha256, sha256_digest
-#else
- 0
-#endif
- },
- {"sha384",
-#ifdef HAVE_SHA384
- SHA384_LEN, NID_sha384, sha384_digest
-#else
- 0
-#endif
- },
- {"sha512",
-#ifdef HAVE_SHA512
- SHA512_LEN, NID_sha512, sha512_digest
-#else
- 0
-#endif
- },
- {NULL}
-};
+}
-static void init_digest_types(ErlNifEnv* env)
+static void init_cipher_types(ErlNifEnv* env)
{
- struct digest_type_t* p = digest_types;
+ struct cipher_type_t* p = cipher_types;
- for (p = digest_types; p->type_str; p++) {
+ for (p = cipher_types; p->type_str; p++) {
p->type_atom = enif_make_atom(env, p->type_str);
}
@@ -2329,31 +2101,45 @@ static struct digest_type_t* get_digest_type(ERL_NIF_TERM type)
return NULL;
}
-static ERL_NIF_TERM rsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Type, Data|{digest,Digest}, Signature, Key=[E,N]) */
- ErlNifBinary data_bin, sign_bin;
- unsigned char hmacbuf[SHA512_LEN];
- ERL_NIF_TERM head, tail, ret;
- int i;
- RSA* rsa;
- const ERL_NIF_TERM type = argv[0];
- const ERL_NIF_TERM* tpl_terms;
- int tpl_arity;
- struct digest_type_t* digp = NULL;
- unsigned char* digest = NULL;
+static struct cipher_type_t* get_cipher_type(ERL_NIF_TERM type, size_t key_len)
+{
+ struct cipher_type_t* p = NULL;
+ for (p = cipher_types; p->type_str; p++) {
+ if (type == p->type_atom && (!p->key_len || key_len == p->key_len)) {
+ return p;
+ }
+ }
+ return NULL;
+}
+static ERL_NIF_TERM rsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Type, Digest, Signature, Key=[E,N]) */
+ ErlNifBinary digest_bin, sign_bin;
+ ERL_NIF_TERM head, tail, ret;
+ int i;
+ RSA *rsa;
+#if OPENSSL_VERSION_NUMBER >= 0x1000000fL
+ EVP_PKEY *pkey;
+ EVP_PKEY_CTX *ctx;
+#endif
+ const EVP_MD *md;
+ const ERL_NIF_TERM type = argv[0];
+ struct digest_type_t *digp = NULL;
digp = get_digest_type(type);
if (!digp) {
return enif_make_badarg(env);
}
- if (!digp->len) {
+ if (!digp->md_func) {
return atom_notsup;
}
rsa = RSA_new();
+ md = digp->md_func();
- if (!enif_inspect_binary(env, argv[2], &sign_bin)
+ if (!enif_inspect_binary(env, argv[1], &digest_bin)
+ || digest_bin.size != EVP_MD_size(md)
+ || !enif_inspect_binary(env, argv[2], &sign_bin)
|| !enif_get_list_cell(env, argv[3], &head, &tail)
|| !get_bn_from_bin(env, head, &rsa->e)
|| !enif_get_list_cell(env, tail, &head, &tail)
@@ -2363,27 +2149,24 @@ static ERL_NIF_TERM rsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM
ret = enif_make_badarg(env);
goto done;
}
- if (enif_get_tuple(env, argv[1], &tpl_arity, &tpl_terms)) {
- if (tpl_arity != 2 || tpl_terms[0] != atom_digest
- || !enif_inspect_binary(env, tpl_terms[1], &data_bin)
- || data_bin.size != digp->len) {
-
- ret = enif_make_badarg(env);
- goto done;
- }
- digest = data_bin.data;
- }
- else if (enif_inspect_binary(env, argv[1], &data_bin)) {
- digest = hmacbuf;
- digp->funcp(data_bin.data, data_bin.size, digest);
- }
- else {
- ret = enif_make_badarg(env);
- goto done;
- }
- i = RSA_verify(digp->NID_type, digest, digp->len,
+#if OPENSSL_VERSION_NUMBER >= 0x1000000fL
+ pkey = EVP_PKEY_new();
+ EVP_PKEY_set1_RSA(pkey, rsa);
+
+ ctx = EVP_PKEY_CTX_new(pkey, NULL);
+ EVP_PKEY_verify_init(ctx);
+ EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING);
+ EVP_PKEY_CTX_set_signature_md(ctx, md);
+
+ i = EVP_PKEY_verify(ctx, sign_bin.data, sign_bin.size,
+ digest_bin.data, digest_bin.size);
+ EVP_PKEY_CTX_free(ctx);
+ EVP_PKEY_free(pkey);
+#else
+ i = RSA_verify(md->type, digest_bin.data, EVP_MD_size(md),
sign_bin.data, sign_bin.size, rsa);
+#endif
ret = (i==1 ? atom_true : atom_false);
@@ -2392,107 +2175,6 @@ done:
return ret;
}
-
-static ERL_NIF_TERM aes_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key, IVec, Data, IsEncrypt) */
- ErlNifBinary key_bin, ivec_bin, data_bin;
- unsigned char ivec[16];
- int enc, i = 0, outlen = 0;
- EVP_CIPHER_CTX ctx;
- const EVP_CIPHER *cipher = NULL;
- unsigned char* ret_ptr;
- ERL_NIF_TERM ret;
-
-
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin)
- || (key_bin.size != 16 && key_bin.size != 32)
- || !enif_inspect_binary(env, argv[1], &ivec_bin)
- || ivec_bin.size != 16
- || !enif_inspect_iolist_as_binary(env, argv[2], &data_bin)
- || data_bin.size % 16 != 0) {
-
- return enif_make_badarg(env);
- }
-
- if (argv[3] == atom_true)
- enc = 1;
- else
- enc = 0;
-
- EVP_CIPHER_CTX_init(&ctx);
-
- if (key_bin.size == 16)
- cipher = EVP_aes_128_cbc();
- else if (key_bin.size == 32)
- cipher = EVP_aes_256_cbc();
-
- memcpy(ivec, ivec_bin.data, 16); /* writeable copy */
-
- /* openssl docs say we need to leave at least 3 blocks available
- at the end of the buffer for EVP calls. let's be safe */
- ret_ptr = enif_make_new_binary(env, data_bin.size + 16*3, &ret);
-
- if (EVP_CipherInit_ex(&ctx, cipher, NULL, key_bin.data, ivec, enc) != 1)
- return enif_make_badarg(env);
-
- /* disable padding, we only handle whole blocks */
- EVP_CIPHER_CTX_set_padding(&ctx, 0);
-
- if (EVP_CipherUpdate(&ctx, ret_ptr, &i, data_bin.data, data_bin.size) != 1)
- return enif_make_badarg(env);
- outlen += i;
- if (EVP_CipherFinal_ex(&ctx, ret_ptr + outlen, &i) != 1)
- return enif_make_badarg(env);
- outlen += i;
-
- EVP_CIPHER_CTX_cleanup(&ctx);
-
- CONSUME_REDS(env,data_bin);
-
- /* the garbage collector is going to love this */
- return enif_make_sub_binary(env, ret, 0, outlen);
-}
-
-static ERL_NIF_TERM aes_ige_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key, IVec, Data, IsEncrypt) */
-#ifdef HAVE_AES_IGE
- ErlNifBinary key_bin, ivec_bin, data_bin;
- AES_KEY aes_key;
- unsigned char ivec[32];
- int i;
- unsigned char* ret_ptr;
- ERL_NIF_TERM ret;
-
-
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin)
- || (key_bin.size != 16 && key_bin.size != 32)
- || !enif_inspect_binary(env, argv[1], &ivec_bin)
- || ivec_bin.size != 32
- || !enif_inspect_iolist_as_binary(env, argv[2], &data_bin)
- || data_bin.size % 16 != 0) {
-
- return enif_make_badarg(env);
- }
-
- if (argv[3] == atom_true) {
- i = AES_ENCRYPT;
- AES_set_encrypt_key(key_bin.data, key_bin.size*8, &aes_key);
- }
- else {
- i = AES_DECRYPT;
- AES_set_decrypt_key(key_bin.data, key_bin.size*8, &aes_key);
- }
-
- ret_ptr = enif_make_new_binary(env, data_bin.size, &ret);
- memcpy(ivec, ivec_bin.data, 32); /* writable copy */
- AES_ige_encrypt(data_bin.data, ret_ptr, data_bin.size, &aes_key, ivec, i);
- CONSUME_REDS(env,data_bin);
- return ret;
-#else
- return atom_notsup;
-#endif
-}
-
static ERL_NIF_TERM do_exor(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Data1, Data2) */
ErlNifBinary d1, d2;
@@ -2500,7 +2182,6 @@ static ERL_NIF_TERM do_exor(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
int i;
ERL_NIF_TERM ret;
-
if (!enif_inspect_iolist_as_binary(env,argv[0], &d1)
|| !enif_inspect_iolist_as_binary(env,argv[1], &d2)
|| d1.size != d2.size) {
@@ -2521,7 +2202,6 @@ static ERL_NIF_TERM rc4_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg
RC4_KEY rc4_key;
ERL_NIF_TERM ret;
-
if (!enif_inspect_iolist_as_binary(env,argv[0], &key)
|| !enif_inspect_iolist_as_binary(env,argv[1], &data)) {
return enif_make_badarg(env);
@@ -2538,7 +2218,6 @@ static ERL_NIF_TERM rc4_set_key(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg
ErlNifBinary key;
ERL_NIF_TERM ret;
-
if (!enif_inspect_iolist_as_binary(env,argv[0], &key)) {
return enif_make_badarg(env);
}
@@ -2554,7 +2233,6 @@ static ERL_NIF_TERM rc4_encrypt_with_state(ErlNifEnv* env, int argc, const ERL_N
RC4_KEY* rc4_key;
ERL_NIF_TERM new_state, new_data;
-
if (!enif_inspect_iolist_as_binary(env,argv[0], &state)
|| state.size != sizeof(RC4_KEY)
|| !enif_inspect_iolist_as_binary(env,argv[1], &data)) {
@@ -2568,34 +2246,6 @@ static ERL_NIF_TERM rc4_encrypt_with_state(ErlNifEnv* env, int argc, const ERL_N
return enif_make_tuple2(env,new_state,new_data);
}
-static ERL_NIF_TERM rc2_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key,IVec,Data,IsEncrypt) */
- ErlNifBinary key_bin, ivec_bin, data_bin;
- RC2_KEY rc2_key;
- ERL_NIF_TERM ret;
- unsigned char iv_copy[8];
-
-
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin)
- || (key_bin.size != 5 && key_bin.size != 8 && key_bin.size != 16)
- || !enif_inspect_binary(env, argv[1], &ivec_bin)
- || ivec_bin.size != 8
- || !enif_inspect_iolist_as_binary(env, argv[2], &data_bin)
- || data_bin.size % 8 != 0) {
- return enif_make_badarg(env);
- }
-
- RC2_set_key(&rc2_key, key_bin.size, key_bin.data, key_bin.size*8);
- memcpy(iv_copy, ivec_bin.data, 8);
- RC2_cbc_encrypt(data_bin.data,
- enif_make_new_binary(env, data_bin.size, &ret),
- data_bin.size, &rc2_key,
- iv_copy,
- (argv[3] == atom_true));
- CONSUME_REDS(env,data_bin);
- return ret;
-}
-
static int get_rsa_private_key(ErlNifEnv* env, ERL_NIF_TERM key, RSA *rsa)
{
/* key=[E,N,D]|[E,N,D,P1,P2,E1,E2,C] */
@@ -2625,41 +2275,32 @@ static int get_rsa_private_key(ErlNifEnv* env, ERL_NIF_TERM key, RSA *rsa)
}
static ERL_NIF_TERM rsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Type, Data|{digest,Digest}, Key=[E,N,D]|[E,N,D,P1,P2,E1,E2,C]) */
- ErlNifBinary data_bin, ret_bin;
- unsigned char hmacbuf[SHA512_LEN];
- unsigned rsa_s_len;
- RSA* rsa;
- int i;
- const ERL_NIF_TERM* tpl_terms;
- int tpl_arity;
+{/* (Type, Digest, Key=[E,N,D]|[E,N,D,P1,P2,E1,E2,C]) */
+ ErlNifBinary digest_bin, ret_bin;
+#if OPENSSL_VERSION_NUMBER >= 0x1000000fL
+ EVP_PKEY *pkey;
+ EVP_PKEY_CTX *ctx;
+ size_t rsa_s_len;
+#else
+ unsigned rsa_s_len, len;
+#endif
+ RSA *rsa;
+ int i;
struct digest_type_t *digp;
- unsigned char* digest;
-
+ const EVP_MD *md;
digp = get_digest_type(argv[0]);
if (!digp) {
return enif_make_badarg(env);
}
- if (!digp->len) {
+ if (!digp->md_func) {
return atom_notsup;
}
+ md = digp->md_func();
- if (enif_get_tuple(env, argv[1], &tpl_arity, &tpl_terms)) {
- if (tpl_arity != 2 || tpl_terms[0] != atom_digest
- || !enif_inspect_binary(env, tpl_terms[1], &data_bin)
- || data_bin.size != digp->len) {
-
- return enif_make_badarg(env);
- }
- digest = data_bin.data;
- }
- else {
- if (!enif_inspect_binary(env,argv[1],&data_bin)) {
- return enif_make_badarg(env);
- }
- digest = hmacbuf;
- digp->funcp(data_bin.data, data_bin.size, digest);
+ if (!enif_inspect_binary(env,argv[1],&digest_bin)
+ || digest_bin.size != EVP_MD_size(md)) {
+ return enif_make_badarg(env);
}
rsa = RSA_new();
@@ -2669,14 +2310,33 @@ static ERL_NIF_TERM rsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
}
+#if OPENSSL_VERSION_NUMBER >= 0x1000000fL
+ pkey = EVP_PKEY_new();
+ EVP_PKEY_set1_RSA(pkey, rsa);
+ rsa_s_len=(size_t)EVP_PKEY_size(pkey);
+ enif_alloc_binary(rsa_s_len, &ret_bin);
+
+ ctx = EVP_PKEY_CTX_new(pkey, NULL);
+ EVP_PKEY_sign_init(ctx);
+ EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING);
+ EVP_PKEY_CTX_set_signature_md(ctx, md);
+
+ i = EVP_PKEY_sign(ctx, ret_bin.data, &rsa_s_len,
+ digest_bin.data, digest_bin.size);
+ ASSERT(i<=0 || rsa_s_len <= ret_bin.size);
+ EVP_PKEY_CTX_free(ctx);
+ EVP_PKEY_free(pkey);
+#else
enif_alloc_binary(RSA_size(rsa), &ret_bin);
+ len = EVP_MD_size(md);
- ERL_VALGRIND_ASSERT_MEM_DEFINED(digest, digp->len);
- i = RSA_sign(digp->NID_type, digest, digp->len,
+ ERL_VALGRIND_ASSERT_MEM_DEFINED(digest_bin.data, len);
+ i = RSA_sign(md->type, digest_bin.data, len,
ret_bin.data, &rsa_s_len, rsa);
+#endif
RSA_free(rsa);
- if (i) {
+ if (i > 0) {
ERL_VALGRIND_MAKE_MEM_DEFINED(ret_bin.data, rsa_s_len);
if (rsa_s_len != ret_bin.size) {
enif_realloc_binary(&ret_bin, rsa_s_len);
@@ -2692,43 +2352,16 @@ static ERL_NIF_TERM rsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
static ERL_NIF_TERM dss_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (DigesType|none, Data|{digest,Digest}, Key=[P,Q,G,PrivKey]) */
- ErlNifBinary data_bin, ret_bin;
+{/* (sha, Digest, Key=[P,Q,G,PrivKey]) */
+ ErlNifBinary digest_bin, ret_bin;
ERL_NIF_TERM head, tail;
- unsigned char hmacbuf[SHA_DIGEST_LENGTH];
unsigned int dsa_s_len;
- const ERL_NIF_TERM* tpl_terms;
- int tpl_arity;
- unsigned char* digest = NULL;
DSA* dsa;
int i;
-
- if (argv[0] == atom_sha) {
- if (enif_get_tuple(env, argv[1], &tpl_arity, &tpl_terms)) {
- if (tpl_arity != 2 || tpl_terms[0] != atom_digest
- || !enif_inspect_binary(env, tpl_terms[1], &data_bin)
- || data_bin.size != SHA_DIGEST_LENGTH) {
-
- return enif_make_badarg(env);
- }
- digest = data_bin.data;
- }
- else {
- if (!enif_inspect_binary(env,argv[1],&data_bin)) {
- return enif_make_badarg(env);
- }
- SHA1(data_bin.data, data_bin.size, hmacbuf);
- digest = hmacbuf;
- }
- }
- else if (argv[0] == atom_none
- && enif_inspect_binary(env,argv[1],&data_bin)
- && data_bin.size == SHA_DIGEST_LENGTH) {
-
- digest = data_bin.data;
- }
- else {
+ if (!argv[0] == atom_sha
+ || !enif_inspect_binary(env, argv[1], &digest_bin)
+ || digest_bin.size != SHA_DIGEST_LENGTH) {
return enif_make_badarg(env);
}
@@ -2749,7 +2382,7 @@ static ERL_NIF_TERM dss_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
}
enif_alloc_binary(DSA_size(dsa), &ret_bin);
- i = DSA_sign(NID_sha1, digest, SHA_DIGEST_LENGTH,
+ i = DSA_sign(NID_sha1, digest_bin.data, SHA_DIGEST_LENGTH,
ret_bin.data, &dsa_s_len, dsa);
DSA_free(dsa);
if (i) {
@@ -2789,7 +2422,6 @@ static ERL_NIF_TERM rsa_public_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TER
int padding, i;
RSA* rsa;
-
rsa = RSA_new();
if (!enif_inspect_binary(env, argv[0], &data_bin)
@@ -2838,7 +2470,6 @@ static ERL_NIF_TERM rsa_private_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TE
int padding, i;
RSA* rsa;
-
rsa = RSA_new();
if (!enif_inspect_binary(env, argv[0], &data_bin)
@@ -2885,7 +2516,6 @@ static ERL_NIF_TERM dh_generate_parameters_nif(ErlNifEnv* env, int argc, const E
unsigned char *p_ptr, *g_ptr;
ERL_NIF_TERM ret_p, ret_g;
-
if (!enif_get_int(env, argv[0], &prime_len)
|| !enif_get_int(env, argv[1], &generator)) {
@@ -2913,7 +2543,6 @@ static ERL_NIF_TERM dh_check(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]
int i;
ERL_NIF_TERM ret, head, tail;
-
dh_params = DH_new();
if (!enif_get_list_cell(env, argv[0], &head, &tail)
@@ -2948,7 +2577,6 @@ static ERL_NIF_TERM dh_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_
ERL_NIF_TERM ret, ret_pub, ret_prv, head, tail;
int mpint; /* 0 or 4 */
-
dh_params = DH_new();
if (!(get_bn_from_bin(env, argv[0], &dh_params->priv_key)
@@ -2993,7 +2621,6 @@ static ERL_NIF_TERM dh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_T
ErlNifBinary ret_bin;
ERL_NIF_TERM ret, head, tail;
-
dh_params = DH_new();
if (!get_bn_from_bin(env, argv[0], &pubkey)
@@ -3016,7 +2643,7 @@ static ERL_NIF_TERM dh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_T
ret = enif_make_binary(env, &ret_bin);
}
else {
- enif_release_binary(&ret_bin);
+ enif_release_binary(&ret_bin);
ret = atom_error;
}
}
@@ -3034,7 +2661,6 @@ static ERL_NIF_TERM srp_value_B_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM
unsigned dlen;
ERL_NIF_TERM ret;
-
if (!get_bn_from_bin(env, argv[0], &bn_multiplier)
|| !get_bn_from_bin(env, argv[1], &bn_verifier)
|| !get_bn_from_bin(env, argv[2], &bn_generator)
@@ -3095,7 +2721,6 @@ static ERL_NIF_TERM srp_user_secret_nif(ErlNifEnv* env, int argc, const ERL_NIF_
unsigned dlen;
ERL_NIF_TERM ret;
-
if (!get_bn_from_bin(env, argv[0], &bn_a)
|| !get_bn_from_bin(env, argv[1], &bn_u)
|| !get_bn_from_bin(env, argv[2], &bn_B)
@@ -3175,7 +2800,6 @@ static ERL_NIF_TERM srp_host_secret_nif(ErlNifEnv* env, int argc, const ERL_NIF_
unsigned dlen;
ERL_NIF_TERM ret;
-
if (!get_bn_from_bin(env, argv[0], &bn_verifier)
|| !get_bn_from_bin(env, argv[1], &bn_b)
|| !get_bn_from_bin(env, argv[2], &bn_u)
@@ -3228,99 +2852,6 @@ static ERL_NIF_TERM srp_host_secret_nif(ErlNifEnv* env, int argc, const ERL_NIF_
return ret;
}
-static ERL_NIF_TERM bf_cfb64_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key, Ivec, Data, IsEncrypt) */
- ErlNifBinary key_bin, ivec_bin, data_bin;
- BF_KEY bf_key; /* blowfish key 8 */
- unsigned char bf_tkey[8]; /* blowfish ivec */
- int bf_n = 0; /* blowfish ivec pos */
- ERL_NIF_TERM ret;
-
-
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin)
- || !enif_inspect_binary(env, argv[1], &ivec_bin)
- || ivec_bin.size != 8
- || !enif_inspect_iolist_as_binary(env, argv[2], &data_bin)) {
- return enif_make_badarg(env);
- }
-
- BF_set_key(&bf_key, key_bin.size, key_bin.data);
- memcpy(bf_tkey, ivec_bin.data, 8);
- BF_cfb64_encrypt(data_bin.data, enif_make_new_binary(env,data_bin.size,&ret),
- data_bin.size, &bf_key, bf_tkey, &bf_n,
- (argv[3] == atom_true ? BF_ENCRYPT : BF_DECRYPT));
- CONSUME_REDS(env,data_bin);
- return ret;
-}
-
-static ERL_NIF_TERM bf_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key, Ivec, Data, IsEncrypt) */
- ErlNifBinary key_bin, ivec_bin, data_bin;
- BF_KEY bf_key; /* blowfish key 8 */
- unsigned char bf_tkey[8]; /* blowfish ivec */
- ERL_NIF_TERM ret;
-
-
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin)
- || !enif_inspect_binary(env, argv[1], &ivec_bin)
- || ivec_bin.size != 8
- || !enif_inspect_iolist_as_binary(env, argv[2], &data_bin)
- || data_bin.size % 8 != 0) {
- return enif_make_badarg(env);
- }
-
- BF_set_key(&bf_key, key_bin.size, key_bin.data);
- memcpy(bf_tkey, ivec_bin.data, 8);
- BF_cbc_encrypt(data_bin.data, enif_make_new_binary(env,data_bin.size,&ret),
- data_bin.size, &bf_key, bf_tkey,
- (argv[3] == atom_true ? BF_ENCRYPT : BF_DECRYPT));
- CONSUME_REDS(env,data_bin);
- return ret;
-}
-
-static ERL_NIF_TERM bf_ecb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key, Data, IsEncrypt) */
- ErlNifBinary key_bin, data_bin;
- BF_KEY bf_key; /* blowfish key 8 */
- ERL_NIF_TERM ret;
-
-
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin)
- || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)
- || data_bin.size < 8) {
- return enif_make_badarg(env);
- }
- BF_set_key(&bf_key, key_bin.size, key_bin.data);
- BF_ecb_encrypt(data_bin.data, enif_make_new_binary(env,data_bin.size,&ret),
- &bf_key, (argv[2] == atom_true ? BF_ENCRYPT : BF_DECRYPT));
- CONSUME_REDS(env,data_bin);
- return ret;
-}
-
-static ERL_NIF_TERM blowfish_ofb64_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key, IVec, Data) */
- ErlNifBinary key_bin, ivec_bin, data_bin;
- BF_KEY bf_key; /* blowfish key 8 */
- unsigned char bf_tkey[8]; /* blowfish ivec */
- int bf_n = 0; /* blowfish ivec pos */
- ERL_NIF_TERM ret;
-
-
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin)
- || !enif_inspect_binary(env, argv[1], &ivec_bin)
- || ivec_bin.size != 8
- || !enif_inspect_iolist_as_binary(env, argv[2], &data_bin)) {
- return enif_make_badarg(env);
- }
-
- BF_set_key(&bf_key, key_bin.size, key_bin.data);
- memcpy(bf_tkey, ivec_bin.data, 8);
- BF_ofb64_encrypt(data_bin.data, enif_make_new_binary(env,data_bin.size,&ret),
- data_bin.size, &bf_key, bf_tkey, &bf_n);
- CONSUME_REDS(env,data_bin);
- return ret;
-}
-
#if defined(HAVE_EC)
static EC_KEY* ec_key_new(ErlNifEnv* env, ERL_NIF_TERM curve_arg)
{
@@ -3629,7 +3160,6 @@ static ERL_NIF_TERM ec_key_generate(ErlNifEnv* env, int argc, const ERL_NIF_TERM
ERL_NIF_TERM priv_key;
ERL_NIF_TERM pub_key = atom_undefined;
-
if (!get_ec_key(env, argv[0], argv[1], atom_undefined, &key))
goto badarg;
@@ -3659,50 +3189,33 @@ badarg:
}
static ERL_NIF_TERM ecdsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Type, Data|{digest,Digest}, Curve, Key) */
+{/* (Type, Digest, Curve, Key) */
#if defined(HAVE_EC)
- ErlNifBinary data_bin, ret_bin;
- unsigned char hmacbuf[SHA_DIGEST_LENGTH];
+ ErlNifBinary digest_bin, ret_bin;
unsigned int dsa_s_len;
EC_KEY* key = NULL;
- int i;
- const ERL_NIF_TERM* tpl_terms;
- int tpl_arity;
+ int i, len;
struct digest_type_t *digp;
- unsigned char* digest;
-
+ const EVP_MD *md;
digp = get_digest_type(argv[0]);
if (!digp) {
return enif_make_badarg(env);
}
- if (!digp->len) {
+ if (!digp->md_func) {
return atom_notsup;
}
+ md = digp->md_func();
+ len = EVP_MD_size(md);
- if (!get_ec_key(env, argv[2], argv[3], atom_undefined, &key))
+ if (!enif_inspect_binary(env,argv[1],&digest_bin)
+ || digest_bin.size != len
+ || !get_ec_key(env, argv[2], argv[3], atom_undefined, &key))
goto badarg;
- if (enif_get_tuple(env, argv[1], &tpl_arity, &tpl_terms)) {
- if (tpl_arity != 2 || tpl_terms[0] != atom_digest
- || !enif_inspect_binary(env, tpl_terms[1], &data_bin)
- || data_bin.size != digp->len) {
-
- goto badarg;
- }
- digest = data_bin.data;
- }
- else {
- if (!enif_inspect_binary(env,argv[1],&data_bin)) {
- goto badarg;
- }
- digest = hmacbuf;
- digp->funcp(data_bin.data, data_bin.size, digest);
- }
-
enif_alloc_binary(ECDSA_size(key), &ret_bin);
- i = ECDSA_sign(digp->NID_type, digest, digp->len,
+ i = ECDSA_sign(md->type, digest_bin.data, len,
ret_bin.data, &dsa_s_len, key);
EC_KEY_free(key);
@@ -3727,49 +3240,32 @@ badarg:
}
static ERL_NIF_TERM ecdsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Type, Data|{digest,Digest}, Signature, Curve, Key) */
+{/* (Type, Digest, Signature, Curve, Key) */
#if defined(HAVE_EC)
- ErlNifBinary data_bin, sign_bin;
- unsigned char hmacbuf[SHA512_LEN];
- int i;
+ ErlNifBinary digest_bin, sign_bin;
+ int i, len;
EC_KEY* key = NULL;
const ERL_NIF_TERM type = argv[0];
- const ERL_NIF_TERM* tpl_terms;
- int tpl_arity;
- struct digest_type_t* digp = NULL;
- unsigned char* digest = NULL;
-
+ struct digest_type_t *digp = NULL;
+ const EVP_MD *md;
digp = get_digest_type(type);
if (!digp) {
return enif_make_badarg(env);
}
- if (!digp->len) {
+ if (!digp->md_func) {
return atom_notsup;
}
+ md = digp->md_func();
+ len = EVP_MD_size(md);
- if (!enif_inspect_binary(env, argv[2], &sign_bin)
+ if (!enif_inspect_binary(env, argv[1], &digest_bin)
+ || digest_bin.size != len
+ || !enif_inspect_binary(env, argv[2], &sign_bin)
|| !get_ec_key(env, argv[3], atom_undefined, argv[4], &key))
goto badarg;
- if (enif_get_tuple(env, argv[1], &tpl_arity, &tpl_terms)) {
- if (tpl_arity != 2 || tpl_terms[0] != atom_digest
- || !enif_inspect_binary(env, tpl_terms[1], &data_bin)
- || data_bin.size != digp->len) {
-
- goto badarg;
- }
- digest = data_bin.data;
- }
- else if (enif_inspect_binary(env, argv[1], &data_bin)) {
- digest = hmacbuf;
- digp->funcp(data_bin.data, data_bin.size, digest);
- }
- else {
- goto badarg;
- }
-
- i = ECDSA_verify(digp->NID_type, digest, digp->len,
+ i = ECDSA_verify(md->type, digest_bin.data, len,
sign_bin.data, sign_bin.size, key);
EC_KEY_free(key);
@@ -3803,7 +3299,6 @@ static ERL_NIF_TERM ecdh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF
EC_POINT *my_ecpoint;
EC_KEY *other_ecdh = NULL;
-
if (!get_ec_key(env, argv[1], argv[2], atom_undefined, &key))
return enif_make_badarg(env);
@@ -3847,252 +3342,9 @@ out_err:
static ERL_NIF_TERM rand_seed_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
ErlNifBinary seed_bin;
+
if (!enif_inspect_binary(env, argv[0], &seed_bin))
return enif_make_badarg(env);
RAND_seed(seed_bin.data,seed_bin.size);
return atom_ok;
}
-
-
-/* HMAC */
-
-static void hmac_md5(unsigned char *key, int klen, unsigned char *dbuf, int dlen,
- unsigned char *hmacbuf)
-{
- MD5_CTX ctx;
- char ipad[HMAC_INT_LEN];
- char opad[HMAC_INT_LEN];
- unsigned char nkey[MD5_LEN];
- int i;
-
- /* Change key if longer than 64 bytes */
- if (klen > HMAC_INT_LEN) {
- MD5(key, klen, nkey);
- key = nkey;
- klen = MD5_LEN;
- }
-
- memset(ipad, '\0', sizeof(ipad));
- memset(opad, '\0', sizeof(opad));
- memcpy(ipad, key, klen);
- memcpy(opad, key, klen);
-
- for (i = 0; i < HMAC_INT_LEN; i++) {
- ipad[i] ^= HMAC_IPAD;
- opad[i] ^= HMAC_OPAD;
- }
-
- /* inner MD5 */
- MD5_Init(&ctx);
- MD5_Update(&ctx, ipad, HMAC_INT_LEN);
- MD5_Update(&ctx, dbuf, dlen);
- MD5_Final((unsigned char *) hmacbuf, &ctx);
- /* outer MD5 */
- MD5_Init(&ctx);
- MD5_Update(&ctx, opad, HMAC_INT_LEN);
- MD5_Update(&ctx, hmacbuf, MD5_LEN);
- MD5_Final((unsigned char *) hmacbuf, &ctx);
-}
-
-static void hmac_sha1(unsigned char *key, int klen,
- unsigned char *dbuf, int dlen,
- unsigned char *hmacbuf)
-{
- SHA_CTX ctx;
- char ipad[HMAC_INT_LEN];
- char opad[HMAC_INT_LEN];
- unsigned char nkey[SHA_LEN];
- int i;
-
- /* Change key if longer than 64 bytes */
- if (klen > HMAC_INT_LEN) {
- SHA1(key, klen, nkey);
- key = nkey;
- klen = SHA_LEN;
- }
-
- memset(ipad, '\0', sizeof(ipad));
- memset(opad, '\0', sizeof(opad));
- memcpy(ipad, key, klen);
- memcpy(opad, key, klen);
-
- for (i = 0; i < HMAC_INT_LEN; i++) {
- ipad[i] ^= HMAC_IPAD;
- opad[i] ^= HMAC_OPAD;
- }
-
- /* inner SHA */
- SHA1_Init(&ctx);
- SHA1_Update(&ctx, ipad, HMAC_INT_LEN);
- SHA1_Update(&ctx, dbuf, dlen);
- SHA1_Final((unsigned char *) hmacbuf, &ctx);
- /* outer SHA */
- SHA1_Init(&ctx);
- SHA1_Update(&ctx, opad, HMAC_INT_LEN);
- SHA1_Update(&ctx, hmacbuf, SHA_LEN);
- SHA1_Final((unsigned char *) hmacbuf, &ctx);
-}
-
-#ifdef HAVE_SHA224
-static void hmac_sha224(unsigned char *key, int klen,
- unsigned char *dbuf, int dlen,
- unsigned char *hmacbuf)
-{
- SHA256_CTX ctx;
- char ipad[HMAC_INT_LEN];
- char opad[HMAC_INT_LEN];
- unsigned char nkey[SHA224_DIGEST_LENGTH];
- int i;
-
- /* Change key if longer than 64 bytes */
- if (klen > HMAC_INT_LEN) {
- SHA224(key, klen, nkey);
- key = nkey;
- klen = SHA224_DIGEST_LENGTH;
- }
-
- memset(ipad, '\0', sizeof(ipad));
- memset(opad, '\0', sizeof(opad));
- memcpy(ipad, key, klen);
- memcpy(opad, key, klen);
-
- for (i = 0; i < HMAC_INT_LEN; i++) {
- ipad[i] ^= HMAC_IPAD;
- opad[i] ^= HMAC_OPAD;
- }
-
- /* inner SHA */
- SHA224_Init(&ctx);
- SHA224_Update(&ctx, ipad, HMAC_INT_LEN);
- SHA224_Update(&ctx, dbuf, dlen);
- SHA224_Final((unsigned char *) hmacbuf, &ctx);
- /* outer SHA */
- SHA224_Init(&ctx);
- SHA224_Update(&ctx, opad, HMAC_INT_LEN);
- SHA224_Update(&ctx, hmacbuf, SHA224_DIGEST_LENGTH);
- SHA224_Final((unsigned char *) hmacbuf, &ctx);
-}
-#endif
-
-#ifdef HAVE_SHA256
-static void hmac_sha256(unsigned char *key, int klen,
- unsigned char *dbuf, int dlen,
- unsigned char *hmacbuf)
-{
- SHA256_CTX ctx;
- char ipad[HMAC_INT_LEN];
- char opad[HMAC_INT_LEN];
- unsigned char nkey[SHA256_DIGEST_LENGTH];
- int i;
-
- /* Change key if longer than 64 bytes */
- if (klen > HMAC_INT_LEN) {
- SHA256(key, klen, nkey);
- key = nkey;
- klen = SHA256_DIGEST_LENGTH;
- }
-
- memset(ipad, '\0', sizeof(ipad));
- memset(opad, '\0', sizeof(opad));
- memcpy(ipad, key, klen);
- memcpy(opad, key, klen);
-
- for (i = 0; i < HMAC_INT_LEN; i++) {
- ipad[i] ^= HMAC_IPAD;
- opad[i] ^= HMAC_OPAD;
- }
-
- /* inner SHA */
- SHA256_Init(&ctx);
- SHA256_Update(&ctx, ipad, HMAC_INT_LEN);
- SHA256_Update(&ctx, dbuf, dlen);
- SHA256_Final((unsigned char *) hmacbuf, &ctx);
- /* outer SHA */
- SHA256_Init(&ctx);
- SHA256_Update(&ctx, opad, HMAC_INT_LEN);
- SHA256_Update(&ctx, hmacbuf, SHA256_DIGEST_LENGTH);
- SHA256_Final((unsigned char *) hmacbuf, &ctx);
-}
-#endif
-
-#ifdef HAVE_SHA384
-static void hmac_sha384(unsigned char *key, int klen,
- unsigned char *dbuf, int dlen,
- unsigned char *hmacbuf)
-{
- SHA512_CTX ctx;
- char ipad[HMAC_INT2_LEN];
- char opad[HMAC_INT2_LEN];
- unsigned char nkey[SHA384_DIGEST_LENGTH];
- int i;
-
- /* Change key if longer than 64 bytes */
- if (klen > HMAC_INT2_LEN) {
- SHA384(key, klen, nkey);
- key = nkey;
- klen = SHA384_DIGEST_LENGTH;
- }
-
- memset(ipad, '\0', sizeof(ipad));
- memset(opad, '\0', sizeof(opad));
- memcpy(ipad, key, klen);
- memcpy(opad, key, klen);
-
- for (i = 0; i < HMAC_INT2_LEN; i++) {
- ipad[i] ^= HMAC_IPAD;
- opad[i] ^= HMAC_OPAD;
- }
-
- /* inner SHA */
- SHA384_Init(&ctx);
- SHA384_Update(&ctx, ipad, HMAC_INT2_LEN);
- SHA384_Update(&ctx, dbuf, dlen);
- SHA384_Final((unsigned char *) hmacbuf, &ctx);
- /* outer SHA */
- SHA384_Init(&ctx);
- SHA384_Update(&ctx, opad, HMAC_INT2_LEN);
- SHA384_Update(&ctx, hmacbuf, SHA384_DIGEST_LENGTH);
- SHA384_Final((unsigned char *) hmacbuf, &ctx);
-}
-#endif
-
-#ifdef HAVE_SHA512
-static void hmac_sha512(unsigned char *key, int klen,
- unsigned char *dbuf, int dlen,
- unsigned char *hmacbuf)
-{
- SHA512_CTX ctx;
- char ipad[HMAC_INT2_LEN];
- char opad[HMAC_INT2_LEN];
- unsigned char nkey[SHA512_DIGEST_LENGTH];
- int i;
-
- /* Change key if longer than 64 bytes */
- if (klen > HMAC_INT2_LEN) {
- SHA512(key, klen, nkey);
- key = nkey;
- klen = SHA512_DIGEST_LENGTH;
- }
-
- memset(ipad, '\0', sizeof(ipad));
- memset(opad, '\0', sizeof(opad));
- memcpy(ipad, key, klen);
- memcpy(opad, key, klen);
-
- for (i = 0; i < HMAC_INT2_LEN; i++) {
- ipad[i] ^= HMAC_IPAD;
- opad[i] ^= HMAC_OPAD;
- }
-
- /* inner SHA */
- SHA512_Init(&ctx);
- SHA512_Update(&ctx, ipad, HMAC_INT2_LEN);
- SHA512_Update(&ctx, dbuf, dlen);
- SHA512_Final((unsigned char *) hmacbuf, &ctx);
- /* outer SHA */
- SHA512_Init(&ctx);
- SHA512_Update(&ctx, opad, HMAC_INT2_LEN);
- SHA512_Update(&ctx, hmacbuf, SHA512_DIGEST_LENGTH);
- SHA512_Final((unsigned char *) hmacbuf, &ctx);
-}
-#endif
diff --git a/lib/crypto/c_src/crypto_callback.c b/lib/crypto/c_src/crypto_callback.c
index e0de16074c..aab43232c9 100644
--- a/lib/crypto/c_src/crypto_callback.c
+++ b/lib/crypto/c_src/crypto_callback.c
@@ -51,8 +51,6 @@
DLLEXPORT struct crypto_callbacks* get_crypto_callbacks(int nlocks);
-static ErlNifRWLock** lock_vec = NULL; /* Static locks used by openssl */
-
static void nomem(size_t size, const char* op)
{
fprintf(stderr, "Out of memory abort. Crypto failed to %s %zu bytes.\r\n",
@@ -84,6 +82,8 @@ static void crypto_free(void* ptr)
#ifdef OPENSSL_THREADS /* vvvvvvvvvvvvvvv OPENSSL_THREADS vvvvvvvvvvvvvvvv */
+static ErlNifRWLock** lock_vec = NULL; /* Static locks used by openssl */
+
#include <openssl/crypto.h>
static INLINE void locking(int mode, ErlNifRWLock* lock)
diff --git a/lib/crypto/doc/src/crypto.xml b/lib/crypto/doc/src/crypto.xml
index 291a5145e4..563a090e98 100644
--- a/lib/crypto/doc/src/crypto.xml
+++ b/lib/crypto/doc/src/crypto.xml
@@ -66,29 +66,29 @@
<section>
<title>DATA TYPES </title>
- <p><code>key_value() = integer() | binary() </code></p>
+ <code>key_value() = integer() | binary() </code>
<p>Always <c>binary()</c> when used as return value</p>
- <p><code>rsa_public() = [key_value()] = [E, N] </code></p>
+ <code>rsa_public() = [key_value()] = [E, N] </code>
<p> Where E is the public exponent and N is public modulus. </p>
- <p><code>rsa_private() = [key_value()] = [E, N, D] | [E, N, D, P1, P2, E1, E2, C] </code></p>
+ <code>rsa_private() = [key_value()] = [E, N, D] | [E, N, D, P1, P2, E1, E2, C] </code>
<p>Where E is the public exponent, N is public modulus and D is
the private exponent.The longer key format contains redundant
information that will make the calculation faster. P1,P2 are first
and second prime factors. E1,E2 are first and second exponents. C
is the CRT coefficient. Terminology is taken from <url href="http://www.ietf.org/rfc/rfc3477.txt"> RFC 3447</url>.</p>
- <p><code>dss_public() = [key_value()] = [P, Q, G, Y] </code></p>
+ <code>dss_public() = [key_value()] = [P, Q, G, Y] </code>
<p>Where P, Q and G are the dss parameters and Y is the public key.</p>
- <p><code>dss_private() = [key_value()] = [P, Q, G, X] </code></p>
+ <code>dss_private() = [key_value()] = [P, Q, G, X] </code>
<p>Where P, Q and G are the dss parameters and X is the private key.</p>
- <p><code>srp_public() = key_value() </code></p>
+ <code>srp_public() = key_value() </code>
<p>Where is <c>A</c> or <c>B</c> from <url href="http://srp.stanford.edu/design.html">SRP design</url></p>
- <p><code>srp_private() = key_value() </code></p>
+ <code>srp_private() = key_value() </code>
<p>Where is <c>a</c> or <c>b</c> from <url href="http://srp.stanford.edu/design.html">SRP design</url></p>
<p>Where Verifier is <c>v</c>, Generator is <c>g</c> and Prime is<c> N</c>, DerivedKey is <c>X</c>, and Scrambler is
@@ -96,29 +96,29 @@
Version = '3' | '6' | '6a'
</p>
- <p><code>dh_public() = key_value() </code></p>
+ <code>dh_public() = key_value() </code>
- <p><code>dh_private() = key_value() </code></p>
+ <code>dh_private() = key_value() </code>
- <p><code>dh_params() = [key_value()] = [P, G] </code></p>
+ <code>dh_params() = [key_value()] = [P, G] </code>
- <p><code>ecdh_public() = key_value() </code></p>
+ <code>ecdh_public() = key_value() </code>
- <p><code>ecdh_private() = key_value() </code></p>
+ <code>ecdh_private() = key_value() </code>
- <p><code>ecdh_params() = ec_named_curve() | ec_explicit_curve()</code></p>
+ <code>ecdh_params() = ec_named_curve() | ec_explicit_curve()</code>
- <p><code>ec_explicit_curve() =
- {ec_field(), Prime :: key_value(), Point :: key_value(), Order :: integer(), CoFactor :: none | integer()} </code></p>
+ <code>ec_explicit_curve() =
+ {ec_field(), Prime :: key_value(), Point :: key_value(), Order :: integer(), CoFactor :: none | integer()} </code>
- <p><code>ec_field() = {prime_field, Prime :: integer()} |
- {characteristic_two_field, M :: integer(), Basis :: ec_basis()}</code></p>
+ <code>ec_field() = {prime_field, Prime :: integer()} |
+ {characteristic_two_field, M :: integer(), Basis :: ec_basis()}</code>
- <p><code>ec_basis() = {tpbasis, K :: non_neg_integer()} |
+ <code>ec_basis() = {tpbasis, K :: non_neg_integer()} |
{ppbasis, K1 :: non_neg_integer(), K2 :: non_neg_integer(), K3 :: non_neg_integer()} |
- onbasis</code></p>
+ onbasis</code>
- <p><code>ec_named_curve() ->
+ <code>ec_named_curve() ->
sect571r1| sect571k1| sect409r1| sect409k1| secp521r1| secp384r1| secp224r1| secp224k1|
secp192k1| secp160r2| secp128r2| secp128r1| sect233r1| sect233k1| sect193r2| sect193r1|
sect131r2| sect131r1| sect283r1| sect283k1| sect163r2| secp256k1| secp160k1| secp160r1|
@@ -128,42 +128,42 @@
brainpoolP224t1| brainpoolP256r1| brainpoolP256t1| brainpoolP320r1| brainpoolP320t1|
brainpoolP384r1| brainpoolP384t1| brainpoolP512r1| brainpoolP512t1
</code>
- Note that the <em>sect</em> curves are GF2m (characteristic two) curves and are only supported if the
+ <p>Note that the <em>sect</em> curves are GF2m (characteristic two) curves and are only supported if the
underlying OpenSSL has support for them.
See also <seealso marker="#supports-0">crypto:supports/0</seealso>
</p>
- <p><code>stream_cipher() = rc4 | aes_ctr </code></p>
+ <code>stream_cipher() = rc4 | aes_ctr </code>
- <p><code>block_cipher() = aes_cbc128 | aes_cfb8 | aes_cfb128 | aes_ige256 | blowfish_cbc |
+ <code>block_cipher() = aes_cbc128 | aes_cfb8 | aes_cfb128 | aes_ige256 | blowfish_cbc |
blowfish_cfb64 | des_cbc | des_cfb | des3_cbc | des3_cbf
- | des_ede3 | rc2_cbc </code></p>
+ | des_ede3 | rc2_cbc </code>
- <p><code>aead_cipher() = aes_gcm | chacha20_poly1305 </code></p>
+ <code>aead_cipher() = aes_gcm | chacha20_poly1305 </code>
- <p><code>stream_key() = aes_key() | rc4_key() </code></p>
+ <code>stream_key() = aes_key() | rc4_key() </code>
- <p><code>block_key() = aes_key() | blowfish_key() | des_key()| des3_key() </code></p>
+ <code>block_key() = aes_key() | blowfish_key() | des_key()| des3_key() </code>
- <p><code>aes_key() = iodata() </code> Key length is 128, 192 or 256 bits</p>
+ <code>aes_key() = iodata() </code> <p>Key length is 128, 192 or 256 bits</p>
- <p><code>rc4_key() = iodata() </code> Variable key length from 8 bits up to 2048 bits (usually between 40 and 256)</p>
+ <code>rc4_key() = iodata() </code> <p>Variable key length from 8 bits up to 2048 bits (usually between 40 and 256)</p>
- <p><code>blowfish_key() = iodata() </code> Variable key length from 32 bits up to 448 bits</p>
+ <code>blowfish_key() = iodata() </code> <p>Variable key length from 32 bits up to 448 bits</p>
- <p><code>des_key() = iodata() </code> Key length is 64 bits (in CBC mode only 8 bits are used)</p>
+ <code>des_key() = iodata() </code> <p>Key length is 64 bits (in CBC mode only 8 bits are used)</p>
- <p><code>des3_key() = [binary(), binary(), binary()] </code> Each key part is 64 bits (in CBC mode only 8 bits are used)</p>
+ <code>des3_key() = [binary(), binary(), binary()] </code> <p>Each key part is 64 bits (in CBC mode only 8 bits are used)</p>
- <p><code>digest_type() = md5 | sha | sha224 | sha256 | sha384 | sha512</code></p>
+ <code>digest_type() = md5 | sha | sha224 | sha256 | sha384 | sha512</code>
- <p><code> hash_algorithms() = md5 | ripemd160 | sha | sha224 | sha256 | sha384 | sha512 </code> md4 is also supported for hash_init/1 and hash/2.
+ <code> hash_algorithms() = md5 | ripemd160 | sha | sha224 | sha256 | sha384 | sha512 </code> <p>md4 is also supported for hash_init/1 and hash/2.
Note that both md4 and md5 are recommended only for compatibility with existing applications.
</p>
- <p><code> cipher_algorithms() = des_cbc | des_cfb | des3_cbc | des3_cbf | des_ede3 |
- blowfish_cbc | blowfish_cfb64 | aes_cbc128 | aes_cfb8 | aes_cfb128| aes_cbc256 | aes_ige256 | aes_gcm | chacha20_poly1305 | rc2_cbc | aes_ctr| rc4 </code> </p>
- <p><code> public_key_algorithms() = rsa |dss | ecdsa | dh | ecdh | ec_gf2m</code>
- Note that ec_gf2m is not strictly a public key algorithm, but a restriction on what curves are supported
+ <code> cipher_algorithms() = des_cbc | des_cfb | des3_cbc | des3_cbf | des_ede3 |
+ blowfish_cbc | blowfish_cfb64 | aes_cbc128 | aes_cfb8 | aes_cfb128| aes_cbc256 | aes_ige256 | aes_gcm | chacha20_poly1305 | rc2_cbc | aes_ctr| rc4 </code>
+ <code> public_key_algorithms() = rsa |dss | ecdsa | dh | ecdh | ec_gf2m</code>
+ <p>Note that ec_gf2m is not strictly a public key algorithm, but a restriction on what curves are supported
with ecdsa and ecdh.
</p>
@@ -381,8 +381,8 @@
</type>
<desc>
<p>Computes a HMAC of type <c>Type</c> from <c>Data</c> using
- <c>Key</c> as the authentication key.</p> <c>MacLength</c>
- will limit the size of the resultant <c>Mac</c>.
+ <c>Key</c> as the authentication key.</p> <p><c>MacLength</c>
+ will limit the size of the resultant <c>Mac</c>.</p>
</desc>
</func>
@@ -601,8 +601,11 @@
</type>
<desc>
<p>Generates N bytes randomly uniform 0..255, and returns the
- result in a binary. Uses the <c>crypto</c> library pseudo-random
- number generator.</p>
+ result in a binary. Uses the <c>crypto</c> library pseudo-random
+ number generator.</p>
+ <p>This function is not recommended for cryptographic purposes.
+ Please use <seealso marker="#strong_rand_bytes/1">
+ strong_rand_bytes/1</seealso> instead.</p>
</desc>
</func>
@@ -650,7 +653,7 @@
<p>Creates a digital signature.</p>
<p>Algorithm <c>dss</c> can only be used together with digest type
<c>sha</c>.</p>
- See also <seealso marker="public_key:public_key#sign-3">public_key:sign/3</seealso>
+ <p>See also <seealso marker="public_key:public_key#sign-3">public_key:sign/3</seealso>.</p>
</desc>
</func>
@@ -802,7 +805,7 @@
<p>Algorithm <c>dss</c> can only be used together with digest type
<c>sha</c>.</p>
- See also <seealso marker="public_key:public_key#verify-4">public_key:verify/4</seealso>
+ <p>See also <seealso marker="public_key:public_key#verify-4">public_key:verify/4</seealso>.</p>
</desc>
</func>
diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl
index 38e71591f3..8722e801a6 100644
--- a/lib/crypto/src/crypto.erl
+++ b/lib/crypto/src/crypto.erl
@@ -210,10 +210,8 @@ supports()->
{Hashs, PubKeys, Ciphers} = algorithms(),
[{hashs, Hashs},
- {ciphers, [des_cbc, des_cfb, des3_cbc, des_ede3, blowfish_cbc,
- blowfish_cfb64, blowfish_ofb64, blowfish_ecb, aes_cbc128, aes_cfb8, aes_cfb128,
- aes_cbc256, rc2_cbc, aes_ctr, rc4, aes_ecb] ++ Ciphers},
- {public_keys, [rsa, dss, dh, srp] ++ PubKeys}
+ {ciphers, Ciphers},
+ {public_keys, PubKeys}
].
info_lib() -> ?nif_stub.
@@ -222,20 +220,14 @@ info_lib() -> ?nif_stub.
hash(Hash, Data0) ->
Data = iolist_to_binary(Data0),
- MaxByts = max_bytes(),
- hash(Hash, Data, erlang:byte_size(Data), MaxByts, initial).
+ MaxBytes = max_bytes(),
+ hash(Hash, Data, erlang:byte_size(Data), MaxBytes).
-spec hash_init('md5'|'md4'|'ripemd160'|
'sha'|'sha224'|'sha256'|'sha384'|'sha512') -> any().
-hash_init(md5) -> {md5, md5_init()};
-hash_init(md4) -> {md4, md4_init()};
-hash_init(sha) -> {sha, sha_init()};
-hash_init(ripemd160) -> {ripemd160, ripemd160_init()};
-hash_init(sha224) -> {sha224, sha224_init()};
-hash_init(sha256) -> {sha256, sha256_init()};
-hash_init(sha384) -> {sha384, sha384_init()};
-hash_init(sha512) -> {sha512, sha512_init()}.
+hash_init(Hash) ->
+ notsup_to_error(hash_init_nif(Hash)).
-spec hash_update(_, iodata()) -> any().
@@ -246,14 +238,8 @@ hash_update(State, Data0) ->
-spec hash_final(_) -> binary().
-hash_final({md5,Context}) -> md5_final(Context);
-hash_final({md4,Context}) -> md4_final(Context);
-hash_final({sha,Context}) -> sha_final(Context);
-hash_final({ripemd160,Context}) -> ripemd160_final(Context);
-hash_final({sha224,Context}) -> sha224_final(Context);
-hash_final({sha256,Context}) -> sha256_final(Context);
-hash_final({sha384,Context}) -> sha384_final(Context);
-hash_final({sha512,Context}) -> sha512_final(Context).
+hash_final(State) ->
+ notsup_to_error(hash_final_nif(State)).
-spec hmac(_, iodata(), iodata()) -> binary().
@@ -265,151 +251,128 @@ hash_final({sha512,Context}) -> sha512_final(Context).
hmac(Type, Key, Data0) ->
Data = iolist_to_binary(Data0),
- hmac(Type, Key, Data, undefined, erlang:byte_size(Data), max_bytes(), initial).
+ hmac(Type, Key, Data, undefined, erlang:byte_size(Data), max_bytes()).
hmac(Type, Key, Data0, MacSize) ->
Data = iolist_to_binary(Data0),
- hmac(Type, Key, Data, MacSize, erlang:byte_size(Data), max_bytes(), initial).
+ hmac(Type, Key, Data, MacSize, erlang:byte_size(Data), max_bytes()).
-
-hmac_init(_Type, _Key) -> ?nif_stub.
+hmac_init(Type, Key) ->
+ notsup_to_error(hmac_init_nif(Type, Key)).
hmac_update(State, Data0) ->
Data = iolist_to_binary(Data0),
hmac_update(State, Data, erlang:byte_size(Data), max_bytes()).
-hmac_final(_Context) -> ? nif_stub.
-hmac_final_n(_Context, _HashLen) -> ? nif_stub.
+
+hmac_final(Context) ->
+ notsup_to_error(hmac_final_nif(Context)).
+hmac_final_n(Context, HashLen) ->
+ notsup_to_error(hmac_final_nif(Context, HashLen)).
%% Ecrypt/decrypt %%%
--spec block_encrypt(des_cbc | des_cfb | des3_cbc | des3_cbf | des_ede3 | blowfish_cbc |
- blowfish_cfb64 | aes_cbc128 | aes_cfb8 | aes_cfb128 | aes_cbc256 | rc2_cbc,
+-spec block_encrypt(des_cbc | des_cfb |
+ des3_cbc | des3_cbf | des_ede3 |
+ blowfish_cbc | blowfish_cfb64 | blowfish_ofb64 |
+ aes_cbc128 | aes_cfb8 | aes_cfb128 | aes_cbc256 | aes_ige256 |
+ rc2_cbc,
Key::iodata(), Ivec::binary(), Data::iodata()) -> binary();
(aes_gcm | chacha20_poly1305, Key::iodata(), Ivec::binary(), {AAD::binary(), Data::iodata()}) -> {binary(), binary()}.
-block_encrypt(des_cbc, Key, Ivec, Data) ->
- des_cbc_encrypt(Key, Ivec, Data);
-block_encrypt(des_cfb, Key, Ivec, Data) ->
- des_cfb_encrypt(Key, Ivec, Data);
-block_encrypt(des3_cbc, [Key1, Key2, Key3], Ivec, Data) ->
- des3_cbc_encrypt(Key1, Key2, Key3, Ivec, Data);
-block_encrypt(des3_cbf, [Key1, Key2, Key3], Ivec, Data) ->
- des3_cfb_encrypt(Key1, Key2, Key3, Ivec, Data);
-block_encrypt(des_ede3, [Key1, Key2, Key3], Ivec, Data) ->
- des_ede3_cbc_encrypt(Key1, Key2, Key3, Ivec, Data);
-block_encrypt(blowfish_cbc, Key, Ivec, Data) ->
- blowfish_cbc_encrypt(Key, Ivec, Data);
-block_encrypt(blowfish_cfb64, Key, Ivec, Data) ->
- blowfish_cfb64_encrypt(Key, Ivec, Data);
-block_encrypt(blowfish_ofb64, Key, Ivec, Data) ->
- blowfish_ofb64_encrypt(Key, Ivec, Data);
-block_encrypt(aes_cbc128, Key, Ivec, Data) ->
- aes_cbc_128_encrypt(Key, Ivec, Data);
-block_encrypt(aes_cbc256, Key, Ivec, Data) ->
- aes_cbc_256_encrypt(Key, Ivec, Data);
+block_encrypt(Type, Key, Ivec, Data) when Type =:= des_cbc;
+ Type =:= des_cfb;
+ Type =:= blowfish_cbc;
+ Type =:= blowfish_cfb64;
+ Type =:= blowfish_ofb64;
+ Type =:= aes_cbc128;
+ Type =:= aes_cfb8;
+ Type =:= aes_cfb128;
+ Type =:= aes_cbc256;
+ Type =:= rc2_cbc ->
+ block_crypt_nif(Type, Key, Ivec, Data, true);
+block_encrypt(Type, Key0, Ivec, Data) when Type =:= des3_cbc;
+ Type =:= des_ede3 ->
+ Key = check_des3_key(Key0),
+ block_crypt_nif(des_ede3_cbc, Key, Ivec, Data, true);
+block_encrypt(des3_cbf, Key0, Ivec, Data) ->
+ Key = check_des3_key(Key0),
+ block_crypt_nif(des_ede3_cbf, Key, Ivec, Data, true);
block_encrypt(aes_ige256, Key, Ivec, Data) ->
- aes_ige_256_encrypt(Key, Ivec, Data);
-block_encrypt(aes_cfb8, Key, Ivec, Data) ->
- aes_cfb_8_encrypt(Key, Ivec, Data);
-block_encrypt(aes_cfb128, Key, Ivec, Data) ->
- aes_cfb_128_encrypt(Key, Ivec, Data);
+ aes_ige_crypt_nif(Key, Ivec, Data, true);
block_encrypt(aes_gcm, Key, Ivec, {AAD, Data}) ->
- case aes_gcm_encrypt(Key, Ivec, AAD, Data) of
- notsup -> erlang:error(notsup);
- Return -> Return
- end;
+ aes_gcm_encrypt(Key, Ivec, AAD, Data);
block_encrypt(chacha20_poly1305, Key, Ivec, {AAD, Data}) ->
- case chacha20_poly1305_encrypt(Key, Ivec, AAD, Data) of
- notsup -> erlang:error(notsup);
- Return -> Return
- end;
-block_encrypt(rc2_cbc, Key, Ivec, Data) ->
- rc2_cbc_encrypt(Key, Ivec, Data).
+ chacha20_poly1305_encrypt(Key, Ivec, AAD, Data).
--spec block_decrypt(des_cbc | des_cfb | des3_cbc | des3_cbf | des_ede3 | blowfish_cbc |
- blowfish_cfb64 | blowfish_ofb64 | aes_cbc128 | aes_cbc256 | aes_ige256 |
- aes_cfb8 | aes_cfb128 | rc2_cbc,
+-spec block_decrypt(des_cbc | des_cfb |
+ des3_cbc | des3_cbf | des_ede3 |
+ blowfish_cbc | blowfish_cfb64 | blowfish_ofb64 |
+ aes_cbc128 | aes_cfb8 | aes_cfb128 | aes_cbc256 | aes_ige256 |
+ rc2_cbc,
Key::iodata(), Ivec::binary(), Data::iodata()) -> binary();
(aes_gcm | chacha20_poly1305, Key::iodata(), Ivec::binary(),
{AAD::binary(), Data::iodata(), Tag::binary()}) -> binary() | error.
-block_decrypt(des_cbc, Key, Ivec, Data) ->
- des_cbc_decrypt(Key, Ivec, Data);
-block_decrypt(des_cfb, Key, Ivec, Data) ->
- des_cfb_decrypt(Key, Ivec, Data);
-block_decrypt(des3_cbc, [Key1, Key2, Key3], Ivec, Data) ->
- des3_cbc_decrypt(Key1, Key2, Key3, Ivec, Data);
-block_decrypt(des3_cbf, [Key1, Key2, Key3], Ivec, Data) ->
- des3_cfb_decrypt(Key1, Key2, Key3, Ivec, Data);
-block_decrypt(des_ede3, [Key1, Key2, Key3], Ivec, Data) ->
- des_ede3_cbc_decrypt(Key1, Key2, Key3, Ivec, Data);
-block_decrypt(blowfish_cbc, Key, Ivec, Data) ->
- blowfish_cbc_decrypt(Key, Ivec, Data);
-block_decrypt(blowfish_cfb64, Key, Ivec, Data) ->
- blowfish_cfb64_decrypt(Key, Ivec, Data);
-block_decrypt(blowfish_ofb64, Key, Ivec, Data) ->
- blowfish_ofb64_decrypt(Key, Ivec, Data);
-block_decrypt(aes_cbc128, Key, Ivec, Data) ->
- aes_cbc_128_decrypt(Key, Ivec, Data);
-block_decrypt(aes_cbc256, Key, Ivec, Data) ->
- aes_cbc_256_decrypt(Key, Ivec, Data);
+block_decrypt(Type, Key, Ivec, Data) when Type =:= des_cbc;
+ Type =:= des_cfb;
+ Type =:= blowfish_cbc;
+ Type =:= blowfish_cfb64;
+ Type =:= blowfish_ofb64;
+ Type =:= aes_cbc128;
+ Type =:= aes_cfb8;
+ Type =:= aes_cfb128;
+ Type =:= aes_cbc256;
+ Type =:= rc2_cbc ->
+ block_crypt_nif(Type, Key, Ivec, Data, false);
+block_decrypt(Type, Key0, Ivec, Data) when Type =:= des3_cbc;
+ Type =:= des_ede3 ->
+ Key = check_des3_key(Key0),
+ block_crypt_nif(des_ede3_cbc, Key, Ivec, Data, false);
+block_decrypt(des3_cbf, Key0, Ivec, Data) ->
+ Key = check_des3_key(Key0),
+ block_crypt_nif(des_ede3_cbf, Key, Ivec, Data, false);
block_decrypt(aes_ige256, Key, Ivec, Data) ->
- aes_ige_256_decrypt(Key, Ivec, Data);
-block_decrypt(aes_cfb8, Key, Ivec, Data) ->
- aes_cfb_8_decrypt(Key, Ivec, Data);
-block_decrypt(aes_cfb128, Key, Ivec, Data) ->
- aes_cfb_128_decrypt(Key, Ivec, Data);
+ notsup_to_error(aes_ige_crypt_nif(Key, Ivec, Data, false));
block_decrypt(aes_gcm, Key, Ivec, {AAD, Data, Tag}) ->
- case aes_gcm_decrypt(Key, Ivec, AAD, Data, Tag) of
- notsup -> erlang:error(notsup);
- Return -> Return
- end;
+ aes_gcm_decrypt(Key, Ivec, AAD, Data, Tag);
block_decrypt(chacha20_poly1305, Key, Ivec, {AAD, Data, Tag}) ->
- case chacha20_poly1305_decrypt(Key, Ivec, AAD, Data, Tag) of
- notsup -> erlang:error(notsup);
- Return -> Return
- end;
-block_decrypt(rc2_cbc, Key, Ivec, Data) ->
- rc2_cbc_decrypt(Key, Ivec, Data).
+ chacha20_poly1305_decrypt(Key, Ivec, AAD, Data, Tag).
-spec block_encrypt(des_ecb | blowfish_ecb | aes_ecb, Key::iodata(), Data::iodata()) -> binary().
-block_encrypt(des_ecb, Key, Data) ->
- des_ecb_encrypt(Key, Data);
-block_encrypt(blowfish_ecb, Key, Data) ->
- blowfish_ecb_encrypt(Key, Data);
-block_encrypt(aes_ecb, Key, Data) ->
- aes_ecb_encrypt(Key, Data).
+block_encrypt(Type, Key, Data) ->
+ block_crypt_nif(Type, Key, Data, true).
-spec block_decrypt(des_ecb | blowfish_ecb | aes_ecb, Key::iodata(), Data::iodata()) -> binary().
-block_decrypt(des_ecb, Key, Data) ->
- des_ecb_decrypt(Key, Data);
-block_decrypt(blowfish_ecb, Key, Data) ->
- blowfish_ecb_decrypt(Key, Data);
-block_decrypt(aes_ecb, Key, Data) ->
- aes_ecb_decrypt(Key, Data).
+block_decrypt(Type, Key, Data) ->
+ block_crypt_nif(Type, Key, Data, false).
-spec next_iv(des_cbc | des3_cbc | aes_cbc | aes_ige, Data::iodata()) -> binary().
-next_iv(des_cbc, Data) ->
- des_cbc_ivec(Data);
-next_iv(des3_cbc, Data) ->
- des_cbc_ivec(Data);
-next_iv(aes_cbc, Data) ->
- aes_cbc_ivec(Data);
-next_iv(aes_ige, Data) ->
- aes_ige_ivec(Data).
+next_iv(Type, Data) when is_binary(Data) ->
+ IVecSize = case Type of
+ des_cbc -> 8;
+ des3_cbc -> 8;
+ aes_cbc -> 16;
+ aes_ige -> 32
+ end,
+ {_, IVec} = split_binary(Data, size(Data) - IVecSize),
+ IVec;
+next_iv(Type, Data) when is_list(Data) ->
+ next_iv(Type, list_to_binary(Data)).
-spec next_iv(des_cfb, Data::iodata(), Ivec::binary()) -> binary().
-next_iv(des_cfb, Data, Ivec) ->
- des_cfb_ivec(Ivec, Data);
+next_iv(des_cfb, Data, IVec) ->
+ IVecAndData = list_to_binary([IVec, Data]),
+ {_, NewIVec} = split_binary(IVecAndData, byte_size(IVecAndData) - 8),
+ NewIVec;
next_iv(Type, Data, _Ivec) ->
next_iv(Type, Data).
stream_init(aes_ctr, Key, Ivec) ->
{aes_ctr, aes_ctr_stream_init(Key, Ivec)}.
stream_init(rc4, Key) ->
- {rc4, rc4_set_key(Key)}.
+ {rc4, notsup_to_error(rc4_set_key(Key))}.
stream_encrypt(State, Data0) ->
Data = iolist_to_binary(Data0),
@@ -485,35 +448,31 @@ verify(dss, none, Data, Signature, Key) when is_binary(Data) ->
verify(dss, sha, {digest, Data}, Signature, Key);
verify(Alg, Type, Data, Signature, Key) when is_binary(Data) ->
verify(Alg, Type, {digest, hash(Type, Data)}, Signature, Key);
-verify(dss, Type, Data, Signature, Key) ->
- dss_verify_nif(Type, Data, Signature, map_ensure_int_as_bin(Key));
-verify(rsa, Type, DataOrDigest, Signature, Key) ->
- case rsa_verify_nif(Type, DataOrDigest, Signature, map_ensure_int_as_bin(Key)) of
- notsup -> erlang:error(notsup);
- Bool -> Bool
- end;
-verify(ecdsa, Type, DataOrDigest, Signature, [Key, Curve]) ->
- case ecdsa_verify_nif(Type, DataOrDigest, Signature, nif_curve_params(Curve), ensure_int_as_bin(Key)) of
- notsup -> erlang:error(notsup);
- Bool -> Bool
- end.
+verify(dss, Type, {digest, Digest}, Signature, Key) ->
+ dss_verify_nif(Type, Digest, Signature, map_ensure_int_as_bin(Key));
+verify(rsa, Type, {digest, Digest}, Signature, Key) ->
+ notsup_to_error(
+ rsa_verify_nif(Type, Digest, Signature, map_ensure_int_as_bin(Key)));
+verify(ecdsa, Type, {digest, Digest}, Signature, [Key, Curve]) ->
+ notsup_to_error(
+ ecdsa_verify_nif(Type, Digest, Signature, nif_curve_params(Curve), ensure_int_as_bin(Key))).
sign(dss, none, Data, Key) when is_binary(Data) ->
sign(dss, sha, {digest, Data}, Key);
sign(Alg, Type, Data, Key) when is_binary(Data) ->
sign(Alg, Type, {digest, hash(Type, Data)}, Key);
-sign(rsa, Type, DataOrDigest, Key) ->
- case rsa_sign_nif(Type, DataOrDigest, map_ensure_int_as_bin(Key)) of
- error -> erlang:error(badkey, [Type,DataOrDigest,Key]);
+sign(rsa, Type, {digest, Digest}, Key) ->
+ case rsa_sign_nif(Type, Digest, map_ensure_int_as_bin(Key)) of
+ error -> erlang:error(badkey, [Type,Digest,Key]);
Sign -> Sign
end;
-sign(dss, Type, DataOrDigest, Key) ->
- case dss_sign_nif(Type, DataOrDigest, map_ensure_int_as_bin(Key)) of
- error -> erlang:error(badkey, [DataOrDigest, Key]);
+sign(dss, Type, {digest, Digest}, Key) ->
+ case dss_sign_nif(Type, Digest, map_ensure_int_as_bin(Key)) of
+ error -> erlang:error(badkey, [Digest, Key]);
Sign -> Sign
end;
-sign(ecdsa, Type, DataOrDigest, [Key, Curve]) ->
- case ecdsa_sign_nif(Type, DataOrDigest, nif_curve_params(Curve), ensure_int_as_bin(Key)) of
- error -> erlang:error(badkey, [Type,DataOrDigest,Key]);
+sign(ecdsa, Type, {digest, Digest}, [Key, Curve]) ->
+ case ecdsa_sign_nif(Type, Digest, nif_curve_params(Curve), ensure_int_as_bin(Key)) of
+ error -> erlang:error(badkey, [Type,Digest,Key]);
Sign -> Sign
end.
@@ -618,8 +577,9 @@ compute_key(srp, HostPublic, {UserPublic, UserPrivate},
HostPubBin, Prime);
[S] -> S
end,
+ notsup_to_error(
srp_user_secret_nif(ensure_int_as_bin(UserPrivate), Scrambler, HostPubBin,
- Multiplier, Generator, DerivedKey, Prime);
+ Multiplier, Generator, DerivedKey, Prime));
compute_key(srp, UserPublic, {HostPublic, HostPrivate},
{host,[Verifier, Prime, Version | ScramblerArg]}) when
@@ -631,8 +591,9 @@ compute_key(srp, UserPublic, {HostPublic, HostPrivate},
[] -> srp_scrambler(Version, UserPubBin, ensure_int_as_bin(HostPublic), Prime);
[S] -> S
end,
+ notsup_to_error(
srp_host_secret_nif(Verifier, ensure_int_as_bin(HostPrivate), Scrambler,
- UserPubBin, Prime);
+ UserPubBin, Prime));
compute_key(ecdh, Others, My, Curve) ->
ecdh_compute_key_nif(ensure_int_as_bin(Others),
@@ -677,7 +638,8 @@ on_load() ->
end
end,
Lib = filename:join([PrivDir, "lib", LibName]),
- Status = case erlang:load_nif(Lib, {?CRYPTO_NIF_VSN,path2bin(Lib)}) of
+ LibBin = path2bin(Lib),
+ Status = case erlang:load_nif(Lib, {?CRYPTO_NIF_VSN,LibBin}) of
ok -> ok;
{error, {load_failed, _}}=Error1 ->
ArchLibDir =
@@ -689,7 +651,8 @@ on_load() ->
[] -> Error1;
_ ->
ArchLib = filename:join([ArchLibDir, LibName]),
- erlang:load_nif(ArchLib, {?CRYPTO_NIF_VSN,path2bin(ArchLib)})
+ ArchBin = path2bin(ArchLib),
+ erlang:load_nif(ArchLib, {?CRYPTO_NIF_VSN,ArchBin})
end;
Error1 -> Error1
end,
@@ -714,46 +677,30 @@ path2bin(Path) when is_list(Path) ->
max_bytes() ->
?MAX_BYTES_TO_NIF.
+notsup_to_error(notsup) ->
+ erlang:error(notsup);
+notsup_to_error(Other) ->
+ Other.
+
%% HASH --------------------------------------------------------------------
-hash(Hash, Data, Size, Max, initial) when Size =< Max ->
- do_hash(Hash, Data);
-hash(State0, Data, Size, Max, continue) when Size =< Max ->
- State = do_hash_update(State0, Data),
- hash_final(State);
-hash(Hash, Data, _Size, Max, initial) ->
- <<Increment:Max/binary, Rest/binary>> = Data,
+hash(Hash, Data, Size, Max) when Size =< Max ->
+ notsup_to_error(hash_nif(Hash, Data));
+hash(Hash, Data, Size, Max) ->
State0 = hash_init(Hash),
- State = do_hash_update(State0, Increment),
- hash(State, Rest, erlang:byte_size(Rest), max_bytes(), continue);
-hash(State0, Data, _Size, MaxByts, continue) ->
- <<Increment:MaxByts/binary, Rest/binary>> = Data,
- State = do_hash_update(State0, Increment),
- hash(State, Rest, erlang:byte_size(Rest), max_bytes(), continue).
-
-do_hash(md5, Data) -> md5(Data);
-do_hash(md4, Data) -> md4(Data);
-do_hash(sha, Data) -> sha(Data);
-do_hash(ripemd160, Data) -> ripemd160(Data);
-do_hash(sha224, Data) -> sha224(Data);
-do_hash(sha256, Data) -> sha256(Data);
-do_hash(sha384, Data) -> sha384(Data);
-do_hash(sha512, Data) -> sha512(Data).
+ State1 = hash_update(State0, Data, Size, Max),
+ hash_final(State1).
hash_update(State, Data, Size, MaxBytes) when Size =< MaxBytes ->
- do_hash_update(State, Data);
+ notsup_to_error(hash_update_nif(State, Data));
hash_update(State0, Data, _, MaxBytes) ->
<<Increment:MaxBytes/binary, Rest/binary>> = Data,
- State = do_hash_update(State0, Increment),
+ State = notsup_to_error(hash_update_nif(State0, Increment)),
hash_update(State, Rest, erlang:byte_size(Rest), MaxBytes).
-do_hash_update({md5,Context}, Data) -> {md5, md5_update(Context,Data)};
-do_hash_update({md4,Context}, Data) -> {md4, md4_update(Context,Data)};
-do_hash_update({sha,Context}, Data) -> {sha, sha_update(Context,Data)};
-do_hash_update({ripemd160,Context}, Data) -> {ripemd160, ripemd160_update(Context,Data)};
-do_hash_update({sha224,Context}, Data) -> {sha224, sha224_update(Context,Data)};
-do_hash_update({sha256,Context}, Data) -> {sha256, sha256_update(Context,Data)};
-do_hash_update({sha384,Context}, Data) -> {sha384, sha384_update(Context,Data)};
-do_hash_update({sha512,Context}, Data) -> {sha512, sha512_update(Context,Data)}.
+hash_nif(_Hash, _Data) -> ?nif_stub.
+hash_init_nif(_Hash) -> ?nif_stub.
+hash_update_nif(_State, _Data) -> ?nif_stub.
+hash_final_nif(_State) -> ?nif_stub.
%%
@@ -765,10 +712,14 @@ do_hash_update({sha512,Context}, Data) -> {sha512, sha512_update(Context,Data
-spec md5_update(binary(), iodata()) -> binary().
-spec md5_final(binary()) -> binary().
-md5(_Data) -> ?nif_stub.
-md5_init() -> ?nif_stub.
-md5_update(_Context, _Data) -> ?nif_stub.
-md5_final(_Context) -> ?nif_stub.
+md5(Data) ->
+ hash(md5, Data).
+md5_init() ->
+ hash_init(md5).
+md5_update(Context, Data) ->
+ hash_update(Context, Data).
+md5_final(Context) ->
+ hash_final(Context).
%%
%% MD4
@@ -778,24 +729,14 @@ md5_final(_Context) -> ?nif_stub.
-spec md4_update(binary(), iodata()) -> binary().
-spec md4_final(binary()) -> binary().
-md4(_Data) -> ?nif_stub.
-md4_init() -> ?nif_stub.
-md4_update(_Context, _Data) -> ?nif_stub.
-md4_final(_Context) -> ?nif_stub.
-
-%%
-%% RIPEMD160
-%%
-
--spec ripemd160(iodata()) -> binary().
--spec ripemd160_init() -> binary().
--spec ripemd160_update(binary(), iodata()) -> binary().
--spec ripemd160_final(binary()) -> binary().
-
-ripemd160(_Data) -> ?nif_stub.
-ripemd160_init() -> ?nif_stub.
-ripemd160_update(_Context, _Data) -> ?nif_stub.
-ripemd160_final(_Context) -> ?nif_stub.
+md4(Data) ->
+ hash(md4, Data).
+md4_init() ->
+ hash_init(md4).
+md4_update(Context, Data) ->
+ hash_update(Context, Data).
+md4_final(Context) ->
+ hash_final(Context).
%%
%% SHA
@@ -805,196 +746,44 @@ ripemd160_final(_Context) -> ?nif_stub.
-spec sha_update(binary(), iodata()) -> binary().
-spec sha_final(binary()) -> binary().
-sha(_Data) -> ?nif_stub.
-sha_init() -> ?nif_stub.
-sha_update(_Context, _Data) -> ?nif_stub.
-sha_final(_Context) -> ?nif_stub.
-
-%
-%% SHA224
-%%
--spec sha224(iodata()) -> binary().
--spec sha224_init() -> binary().
--spec sha224_update(binary(), iodata()) -> binary().
--spec sha224_final(binary()) -> binary().
-
-sha224(Data) ->
- case sha224_nif(Data) of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
-sha224_init() ->
- case sha224_init_nif() of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
-sha224_update(Context, Data) ->
- case sha224_update_nif(Context, Data) of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
-sha224_final(Context) ->
- case sha224_final_nif(Context) of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
-
-sha224_nif(_Data) -> ?nif_stub.
-sha224_init_nif() -> ?nif_stub.
-sha224_update_nif(_Context, _Data) -> ?nif_stub.
-sha224_final_nif(_Context) -> ?nif_stub.
-
-%
-%% SHA256
-%%
--spec sha256(iodata()) -> binary().
--spec sha256_init() -> binary().
--spec sha256_update(binary(), iodata()) -> binary().
--spec sha256_final(binary()) -> binary().
-
-sha256(Data) ->
- case sha256_nif(Data) of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
-sha256_init() ->
- case sha256_init_nif() of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
-sha256_update(Context, Data) ->
- case sha256_update_nif(Context, Data) of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
-sha256_final(Context) ->
- case sha256_final_nif(Context) of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
-
-sha256_nif(_Data) -> ?nif_stub.
-sha256_init_nif() -> ?nif_stub.
-sha256_update_nif(_Context, _Data) -> ?nif_stub.
-sha256_final_nif(_Context) -> ?nif_stub.
-
-%
-%% SHA384
-%%
--spec sha384(iodata()) -> binary().
--spec sha384_init() -> binary().
--spec sha384_update(binary(), iodata()) -> binary().
--spec sha384_final(binary()) -> binary().
-
-sha384(Data) ->
- case sha384_nif(Data) of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
-sha384_init() ->
- case sha384_init_nif() of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
-sha384_update(Context, Data) ->
- case sha384_update_nif(Context, Data) of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
-sha384_final(Context) ->
- case sha384_final_nif(Context) of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
-
-sha384_nif(_Data) -> ?nif_stub.
-sha384_init_nif() -> ?nif_stub.
-sha384_update_nif(_Context, _Data) -> ?nif_stub.
-sha384_final_nif(_Context) -> ?nif_stub.
-
-%
-%% SHA512
-%%
--spec sha512(iodata()) -> binary().
--spec sha512_init() -> binary().
--spec sha512_update(binary(), iodata()) -> binary().
--spec sha512_final(binary()) -> binary().
-
-sha512(Data) ->
- case sha512_nif(Data) of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
-sha512_init() ->
- case sha512_init_nif() of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
-sha512_update(Context, Data) ->
- case sha512_update_nif(Context, Data) of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
-sha512_final(Context) ->
- case sha512_final_nif(Context) of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
-
-sha512_nif(_Data) -> ?nif_stub.
-sha512_init_nif() -> ?nif_stub.
-sha512_update_nif(_Context, _Data) -> ?nif_stub.
-sha512_final_nif(_Context) -> ?nif_stub.
+sha(Data) ->
+ hash(sha, Data).
+sha_init() ->
+ hash_init(sha).
+sha_update(Context, Data) ->
+ hash_update(Context, Data).
+sha_final(Context) ->
+ hash_final(Context).
%% HMAC --------------------------------------------------------------------
-hmac(Type, Key, Data, MacSize, Size, MaxBytes, initial) when Size =< MaxBytes ->
+hmac(Type, Key, Data, MacSize, Size, MaxBytes) when Size =< MaxBytes ->
+ notsup_to_error(
case MacSize of
- undefined ->
- do_hmac(Type, Key, Data);
- _ ->
- do_hmac(Type, Key, Data, MacSize)
- end;
-hmac(Type, Key, Data, MacSize, _, MaxBytes, initial) ->
- <<Increment:MaxBytes/binary, Rest/binary>> = Data,
+ undefined -> hmac_nif(Type, Key, Data);
+ _ -> hmac_nif(Type, Key, Data, MacSize)
+ end);
+hmac(Type, Key, Data, MacSize, Size, MaxBytes) ->
State0 = hmac_init(Type, Key),
- State = hmac_update(State0, Increment),
- hmac(State, Rest, MacSize, erlang:byte_size(Rest), max_bytes(), continue).
-hmac(State0, Data, MacSize, Size, MaxBytes, continue) when Size =< MaxBytes ->
- State = hmac_update(State0, Data),
+ State1 = hmac_update(State0, Data, Size, MaxBytes),
case MacSize of
- undefined ->
- hmac_final(State);
- _ ->
- hmac_final_n(State, MacSize)
- end;
-hmac(State0, Data, MacSize, _Size, MaxBytes, continue) ->
- <<Increment:MaxBytes/binary, Rest/binary>> = Data,
- State = hmac_update(State0, Increment),
- hmac(State, Rest, MacSize, erlang:byte_size(Rest), max_bytes(), continue).
+ undefined -> hmac_final(State1);
+ _ -> hmac_final_n(State1, MacSize)
+ end.
hmac_update(State, Data, Size, MaxBytes) when Size =< MaxBytes ->
- do_hmac_update(State, Data);
+ notsup_to_error(hmac_update_nif(State, Data));
hmac_update(State0, Data, _, MaxBytes) ->
<<Increment:MaxBytes/binary, Rest/binary>> = Data,
- State = do_hmac_update(State0, Increment),
+ State = notsup_to_error(hmac_update_nif(State0, Increment)),
hmac_update(State, Rest, erlang:byte_size(Rest), MaxBytes).
-do_hmac(md5, Key, Data) -> md5_mac(Key, Data);
-do_hmac(sha, Key, Data) -> sha_mac(Key, Data);
-do_hmac(sha224, Key, Data) -> sha224_mac(Key, Data);
-do_hmac(sha256, Key, Data) -> sha256_mac(Key, Data);
-do_hmac(sha384, Key, Data) -> sha384_mac(Key, Data);
-do_hmac(sha512, Key, Data) -> sha512_mac(Key, Data).
-
-do_hmac(md5, Key, Data, Size) -> md5_mac_n(Key, Data, Size);
-do_hmac(sha, Key, Data, Size) -> sha_mac_n(Key, Data, Size);
-do_hmac(sha224, Key, Data, Size) -> sha224_mac(Key, Data, Size);
-do_hmac(sha256, Key, Data, Size) -> sha256_mac(Key, Data, Size);
-do_hmac(sha384, Key, Data, Size) -> sha384_mac(Key, Data, Size);
-do_hmac(sha512, Key, Data, Size) -> sha512_mac(Key, Data, Size).
-
-do_hmac_update(_Context, _Data) -> ? nif_stub.
+hmac_nif(_Type, _Key, _Data) -> ?nif_stub.
+hmac_nif(_Type, _Key, _Data, _MacSize) -> ?nif_stub.
+hmac_init_nif(_Type, _Key) -> ?nif_stub.
+hmac_update_nif(_Context, _Data) -> ?nif_stub.
+hmac_final_nif(_Context) -> ?nif_stub.
+hmac_final_nif(_Context, _MacSize) -> ?nif_stub.
%%
%% MD5_MAC
@@ -1002,97 +791,37 @@ do_hmac_update(_Context, _Data) -> ? nif_stub.
-spec md5_mac(iodata(), iodata()) -> binary().
-spec md5_mac_96(iodata(), iodata()) -> binary().
-md5_mac(Key, Data) ->
- md5_mac_n(Key,Data,16).
+md5_mac(Key, Data) -> hmac(md5, Key, Data).
-md5_mac_96(Key, Data) ->
- md5_mac_n(Key,Data,12).
+md5_mac_96(Key, Data) -> hmac(md5, Key, Data, 12).
-md5_mac_n(_Key,_Data,_MacSz) -> ?nif_stub.
-
%%
%% SHA_MAC
%%
-spec sha_mac(iodata(), iodata()) -> binary().
-spec sha_mac_96(iodata(), iodata()) -> binary().
-sha_mac(Key, Data) ->
- sha_mac_n(Key,Data,20).
-
-sha_mac(Key, Data, Size) ->
- sha_mac_n(Key, Data, Size).
-
-sha_mac_96(Key, Data) ->
- sha_mac_n(Key,Data,12).
-
-sha_mac_n(_Key,_Data,_MacSz) -> ?nif_stub.
-
-%%
-%% SHA224_MAC
-%%
--spec sha224_mac(iodata(), iodata()) -> binary().
-
-sha224_mac(Key, Data) ->
- sha224_mac(Key, Data, 224 div 8).
-
-sha224_mac(Key, Data, Size) ->
- case sha224_mac_nif(Key, Data, Size) of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
-
-sha224_mac_nif(_Key,_Data,_MacSz) -> ?nif_stub.
-
-%%
-%% SHA256_MAC
-%%
--spec sha256_mac(iodata(), iodata()) -> binary().
-
-sha256_mac(Key, Data) ->
- sha256_mac(Key, Data, 256 div 8).
-
-sha256_mac(Key, Data, Size) ->
- case sha256_mac_nif(Key, Data, Size) of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
-
-sha256_mac_nif(_Key,_Data,_MacSz) -> ?nif_stub.
-
-%%
-%% SHA384_MAC
-%%
--spec sha384_mac(iodata(), iodata()) -> binary().
-
-sha384_mac(Key, Data) ->
- sha384_mac(Key, Data, 384 div 8).
+sha_mac(Key, Data) -> hmac(sha, Key, Data).
-sha384_mac(Key, Data, Size) ->
- case sha384_mac_nif(Key, Data, Size) of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
-
-sha384_mac_nif(_Key,_Data,_MacSz) -> ?nif_stub.
+sha_mac(Key, Data, Size) -> hmac(sha, Key, Data, Size).
-%%
-%% SHA512_MAC
-%%
--spec sha512_mac(iodata(), iodata()) -> binary().
+sha_mac_96(Key, Data) -> hmac(sha, Key, Data, 12).
-sha512_mac(Key, Data) ->
- sha512_mac(Key, Data, 512 div 8).
+%% CIPHERS --------------------------------------------------------------------
-sha512_mac(Key, Data, MacSz) ->
- case sha512_mac_nif(Key, Data, MacSz) of
- notsup -> erlang:error(notsup);
- Bin -> Bin
+block_crypt_nif(_Type, _Key, _Ivec, _Text, _IsEncrypt) -> ?nif_stub.
+block_crypt_nif(_Type, _Key, _Text, _IsEncrypt) -> ?nif_stub.
+
+check_des3_key(Key) ->
+ case lists:map(fun erlang:iolist_to_binary/1, Key) of
+ ValidKey = [B1, B2, B3] when byte_size(B1) =:= 8,
+ byte_size(B2) =:= 8,
+ byte_size(B3) =:= 8 ->
+ ValidKey;
+ _ ->
+ error(badarg)
end.
-sha512_mac_nif(_Key,_Data,_MacSz) -> ?nif_stub.
-
-%% CIPHERS --------------------------------------------------------------------
-
%%
%% DES - in electronic codebook mode (ECB)
%%
@@ -1100,10 +829,9 @@ sha512_mac_nif(_Key,_Data,_MacSz) -> ?nif_stub.
-spec des_ecb_decrypt(iodata(), iodata()) -> binary().
des_ecb_encrypt(Key, Data) ->
- des_ecb_crypt(Key, Data, true).
+ block_encrypt(des_ecb, Key, Data).
des_ecb_decrypt(Key, Data) ->
- des_ecb_crypt(Key, Data, false).
-des_ecb_crypt(_Key, _Data, _IsEncrypt) -> ?nif_stub.
+ block_decrypt(des_ecb, Key, Data).
%%
%% DES3 - in cipher block chaining mode (CBC)
@@ -1114,16 +842,14 @@ des_ecb_crypt(_Key, _Data, _IsEncrypt) -> ?nif_stub.
binary().
des3_cbc_encrypt(Key1, Key2, Key3, IVec, Data) ->
- des_ede3_cbc_crypt(Key1, Key2, Key3, IVec, Data, true).
+ block_encrypt(des3_cbc, [Key1, Key2, Key3], IVec, Data).
des_ede3_cbc_encrypt(Key1, Key2, Key3, IVec, Data) ->
- des_ede3_cbc_crypt(Key1, Key2, Key3, IVec, Data, true).
+ block_encrypt(des_ede3, [Key1, Key2, Key3], IVec, Data).
des3_cbc_decrypt(Key1, Key2, Key3, IVec, Data) ->
- des_ede3_cbc_crypt(Key1, Key2, Key3, IVec, Data, false).
+ block_decrypt(des3_cbc, [Key1, Key2, Key3], IVec, Data).
des_ede3_cbc_decrypt(Key1, Key2, Key3, IVec, Data) ->
- des_ede3_cbc_crypt(Key1, Key2, Key3, IVec, Data, false).
-
-des_ede3_cbc_crypt(_Key1, _Key2, _Key3, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
+ block_decrypt(des_ede3, [Key1, Key2, Key3], IVec, Data).
%%
%% DES3 - in 8-bits cipher feedback mode (CFB)
@@ -1134,18 +860,10 @@ des_ede3_cbc_crypt(_Key1, _Key2, _Key3, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
binary().
des3_cfb_encrypt(Key1, Key2, Key3, IVec, Data) ->
- des_ede3_cfb_crypt(Key1, Key2, Key3, IVec, Data, true).
+ block_encrypt(des3_cbf, [Key1, Key2, Key3], IVec, Data).
des3_cfb_decrypt(Key1, Key2, Key3, IVec, Data) ->
- des_ede3_cfb_crypt(Key1, Key2, Key3, IVec, Data, false).
-
-des_ede3_cfb_crypt(Key1, Key2, Key3, IVec, Data, IsEncrypt) ->
- case des_ede3_cfb_crypt_nif(Key1,Key2,Key3,IVec,Data,IsEncrypt) of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
-
-des_ede3_cfb_crypt_nif(_Key1, _Key2, _Key3, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
+ block_decrypt(des3_cbf, [Key1, Key2, Key3], IVec, Data).
%%
%% Blowfish
@@ -1159,62 +877,38 @@ des_ede3_cfb_crypt_nif(_Key1, _Key2, _Key3, _IVec, _Data, _IsEncrypt) -> ?nif_st
-spec blowfish_ofb64_encrypt(iodata(), binary(), iodata()) -> binary().
blowfish_ecb_encrypt(Key, Data) ->
- bf_ecb_crypt(Key,Data, true).
+ block_encrypt(blowfish_ecb, Key, Data).
blowfish_ecb_decrypt(Key, Data) ->
- bf_ecb_crypt(Key,Data, false).
-
-bf_ecb_crypt(_Key,_Data,_IsEncrypt) -> ?nif_stub.
+ block_decrypt(blowfish_ecb, Key, Data).
blowfish_cbc_encrypt(Key, IVec, Data) ->
- bf_cbc_crypt(Key,IVec,Data,true).
+ block_encrypt(blowfish_cbc, Key, IVec, Data).
blowfish_cbc_decrypt(Key, IVec, Data) ->
- bf_cbc_crypt(Key,IVec,Data,false).
-
-bf_cbc_crypt(_Key,_IVec,_Data,_IsEncrypt) -> ?nif_stub.
+ block_decrypt(blowfish_cbc, Key, IVec, Data).
blowfish_cfb64_encrypt(Key, IVec, Data) ->
- bf_cfb64_crypt(Key, IVec, Data, true).
+ block_encrypt(blowfish_cfb64, Key, IVec, Data).
blowfish_cfb64_decrypt(Key, IVec, Data) ->
- bf_cfb64_crypt(Key, IVec, Data, false).
-
-bf_cfb64_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
-
-blowfish_ofb64_decrypt(Key, Ivec, Data) ->
- blowfish_ofb64_encrypt(Key, Ivec, Data).
+ block_decrypt(blowfish_cfb64, Key, IVec, Data).
-blowfish_ofb64_encrypt(_Key, _IVec, _Data) -> ?nif_stub.
+blowfish_ofb64_encrypt(Key, IVec, Data) ->
+ block_encrypt(blowfish_ofb64, Key, IVec, Data).
%%
-%% AES in cipher feedback mode (CFB) - 8 bit shift
-%%
--spec aes_cfb_8_encrypt(iodata(), binary(), iodata()) -> binary().
--spec aes_cfb_8_decrypt(iodata(), binary(), iodata()) -> binary().
-
-aes_cfb_8_encrypt(Key, IVec, Data) ->
- aes_cfb_8_crypt(Key, IVec, Data, true).
-
-aes_cfb_8_decrypt(Key, IVec, Data) ->
- aes_cfb_8_crypt(Key, IVec, Data, false).
-
-aes_cfb_8_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
-
-%%
%% AES in cipher feedback mode (CFB) - 128 bit shift
%%
-spec aes_cfb_128_encrypt(iodata(), binary(), iodata()) -> binary().
-spec aes_cfb_128_decrypt(iodata(), binary(), iodata()) -> binary().
aes_cfb_128_encrypt(Key, IVec, Data) ->
- aes_cfb_128_crypt(Key, IVec, Data, true).
+ block_encrypt(aes_cfb128, Key, IVec, Data).
aes_cfb_128_decrypt(Key, IVec, Data) ->
- aes_cfb_128_crypt(Key, IVec, Data, false).
-
-aes_cfb_128_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
+ block_decrypt(aes_cfb128, Key, IVec, Data).
%%
%% AES - in Galois/Counter Mode (GCM)
@@ -1235,12 +929,10 @@ chacha20_poly1305_decrypt(_Key, _Ivec, _AAD, _In, _Tag) -> ?nif_stub.
-spec des_cbc_decrypt(iodata(), binary(), iodata()) -> binary().
des_cbc_encrypt(Key, IVec, Data) ->
- des_cbc_crypt(Key, IVec, Data, true).
+ block_encrypt(des_cbc, Key, IVec, Data).
des_cbc_decrypt(Key, IVec, Data) ->
- des_cbc_crypt(Key, IVec, Data, false).
-
-des_cbc_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
+ block_decrypt(des_cbc, Key, IVec, Data).
%%
%% dec_cbc_ivec(Data) -> binary()
@@ -1250,11 +942,8 @@ des_cbc_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
%%
-spec des_cbc_ivec(iodata()) -> binary().
-des_cbc_ivec(Data) when is_binary(Data) ->
- {_, IVec} = split_binary(Data, size(Data) - 8),
- IVec;
-des_cbc_ivec(Data) when is_list(Data) ->
- des_cbc_ivec(list_to_binary(Data)).
+des_cbc_ivec(Data) ->
+ next_iv(des_cbc, Data).
%%
%% DES - in 8-bits cipher feedback mode (CFB)
@@ -1263,12 +952,10 @@ des_cbc_ivec(Data) when is_list(Data) ->
-spec des_cfb_decrypt(iodata(), binary(), iodata()) -> binary().
des_cfb_encrypt(Key, IVec, Data) ->
- des_cfb_crypt(Key, IVec, Data, true).
+ block_encrypt(des_cfb, Key, IVec, Data).
des_cfb_decrypt(Key, IVec, Data) ->
- des_cfb_crypt(Key, IVec, Data, false).
-
-des_cfb_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
+ block_decrypt(des_cfb, Key, IVec, Data).
%%
%% dec_cfb_ivec(IVec, Data) -> binary()
@@ -1280,9 +967,7 @@ des_cfb_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
-spec des_cfb_ivec(iodata(), iodata()) -> binary().
des_cfb_ivec(IVec, Data) ->
- IVecAndData = list_to_binary([IVec, Data]),
- {_, NewIVec} = split_binary(IVecAndData, byte_size(IVecAndData) - 8),
- NewIVec.
+ next_iv(des_cfb, Data, IVec).
%%
@@ -1298,18 +983,16 @@ des_cfb_ivec(IVec, Data) ->
binary().
aes_cbc_128_encrypt(Key, IVec, Data) ->
- aes_cbc_crypt(Key, IVec, Data, true).
+ block_encrypt(aes_cbc128, Key, IVec, Data).
aes_cbc_128_decrypt(Key, IVec, Data) ->
- aes_cbc_crypt(Key, IVec, Data, false).
+ block_decrypt(aes_cbc128, Key, IVec, Data).
aes_cbc_256_encrypt(Key, IVec, Data) ->
- aes_cbc_crypt(Key, IVec, Data, true).
+ block_encrypt(aes_cbc256, Key, IVec, Data).
aes_cbc_256_decrypt(Key, IVec, Data) ->
- aes_cbc_crypt(Key, IVec, Data, false).
-
-aes_cbc_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
+ block_decrypt(aes_cbc256, Key, IVec, Data).
%%
%% aes_cbc_ivec(Data) -> binary()
@@ -1318,47 +1001,15 @@ aes_cbc_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
%% aes_cbc_*_[encrypt|decrypt].
%% IVec size: 16 bytes
%%
-aes_cbc_ivec(Data) when is_binary(Data) ->
- {_, IVec} = split_binary(Data, size(Data) - 16),
- IVec;
-aes_cbc_ivec(Data) when is_list(Data) ->
- aes_cbc_ivec(list_to_binary(Data)).
-
+aes_cbc_ivec(Data) ->
+ next_iv(aes_cbc, Data).
%%
%% AES - with 256 bit key in infinite garble extension mode (IGE)
%%
--spec aes_ige_256_decrypt(iodata(), binary(), iodata()) ->
- binary().
-
-aes_ige_256_encrypt(Key, IVec, Data) ->
- aes_ige_crypt(Key, IVec, Data, true).
-
-aes_ige_256_decrypt(Key, IVec, Data) ->
- aes_ige_crypt(Key, IVec, Data, false).
-
-aes_ige_crypt(Key, IVec, Data, IsEncrypt) ->
- case aes_ige_crypt_nif(Key,IVec,Data,IsEncrypt) of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
-
aes_ige_crypt_nif(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
-%%
-%% aes_ige_ivec(Data) -> binary()
-%%
-%% Returns the IVec to be used in the next iteration of
-%% aes_ige_*_[encrypt|decrypt].
-%% IVec size: 32 bytes
-%%
-aes_ige_ivec(Data) when is_binary(Data) ->
- {_, IVec} = split_binary(Data, size(Data) - 32),
- IVec;
-aes_ige_ivec(Data) when is_list(Data) ->
- aes_ige_ivec(list_to_binary(Data)).
-
%% Stream ciphers --------------------------------------------------------------------
@@ -1397,22 +1048,11 @@ do_stream_decrypt({rc4, State0}, Data) ->
aes_ctr_encrypt(_Key, _IVec, _Data) -> ?nif_stub.
aes_ctr_decrypt(_Key, _IVec, _Cipher) -> ?nif_stub.
-%%
-%% AES - in electronic codebook mode (ECB)
-%%
-aes_ecb_encrypt(Key, Data) ->
- aes_ecb_crypt(Key, Data, true).
-
-aes_ecb_decrypt(Key, Data) ->
- aes_ecb_crypt(Key, Data, false).
-
-aes_ecb_crypt(_Key, __Data, _IsEncrypt) -> ?nif_stub.
-
%%
%% AES - in counter mode (CTR) with state maintained for multi-call streaming
%%
--type ctr_state() :: { iodata(), binary(), binary(), integer() }.
+-type ctr_state() :: { iodata(), binary(), binary(), integer() } | binary().
-spec aes_ctr_stream_init(iodata(), binary()) -> ctr_state().
-spec aes_ctr_stream_encrypt(ctr_state(), binary()) ->
@@ -1420,10 +1060,9 @@ aes_ecb_crypt(_Key, __Data, _IsEncrypt) -> ?nif_stub.
-spec aes_ctr_stream_decrypt(ctr_state(), binary()) ->
{ ctr_state(), binary() }.
-aes_ctr_stream_init(Key, IVec) ->
- {Key, IVec, << 0:128 >>, 0}.
-aes_ctr_stream_encrypt({_Key, _IVec, _ECount, _Num}=_State, _Data) -> ?nif_stub.
-aes_ctr_stream_decrypt({_Key, _IVec, _ECount, _Num}=_State, _Cipher) -> ?nif_stub.
+aes_ctr_stream_init(_Key, _IVec) -> ?nif_stub.
+aes_ctr_stream_encrypt(_State, _Data) -> ?nif_stub.
+aes_ctr_stream_decrypt(_State, _Cipher) -> ?nif_stub.
%%
%% RC4 - symmetric stream cipher
@@ -1438,21 +1077,19 @@ rc4_encrypt_with_state(_State, _Data) -> ?nif_stub.
%% RC2 block cipher
rc2_cbc_encrypt(Key, IVec, Data) ->
- rc2_cbc_crypt(Key,IVec,Data,true).
+ block_encrypt(rc2_cbc, Key, IVec, Data).
rc2_cbc_decrypt(Key, IVec, Data) ->
- rc2_cbc_crypt(Key,IVec,Data,false).
-
-rc2_cbc_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
+ block_decrypt(rc2_cbc, Key, IVec, Data).
%%
%% RC2 - 40 bits block cipher - Backwards compatibility not documented.
%%
rc2_40_cbc_encrypt(Key, IVec, Data) when erlang:byte_size(Key) == 5 ->
- rc2_cbc_crypt(Key,IVec,Data,true).
+ block_encrypt(rc2_cbc, Key, IVec, Data).
rc2_40_cbc_decrypt(Key, IVec, Data) when erlang:byte_size(Key) == 5 ->
- rc2_cbc_crypt(Key,IVec,Data,false).
+ block_decrypt(rc2_cbc, Key, IVec, Data).
%% Secure remote password -------------------------------------------------------------------
@@ -1470,16 +1107,18 @@ host_srp_gen_key(Private, Verifier, Generator, Prime, Version) ->
case srp_value_B_nif(Multiplier, Verifier, Generator, Private, Prime) of
error ->
error;
+ notsup ->
+ erlang:error(notsup);
Public ->
{Public, Private}
end.
srp_multiplier('6a', Generator, Prime) ->
%% k = SHA1(N | PAD(g)) from http://srp.stanford.edu/design.html
- C0 = sha_init(),
- C1 = sha_update(C0, Prime),
- C2 = sha_update(C1, srp_pad_to(erlang:byte_size(Prime), Generator)),
- sha_final(C2);
+ C0 = hash_init(sha),
+ C1 = hash_update(C0, Prime),
+ C2 = hash_update(C1, srp_pad_to(erlang:byte_size(Prime), Generator)),
+ hash_final(C2);
srp_multiplier('6', _, _) ->
<<3/integer>>;
srp_multiplier('3', _, _) ->
@@ -1488,10 +1127,10 @@ srp_multiplier('3', _, _) ->
srp_scrambler(Version, UserPublic, HostPublic, Prime) when Version == '6'; Version == '6a'->
%% SHA1(PAD(A) | PAD(B)) from http://srp.stanford.edu/design.html
PadLength = erlang:byte_size(Prime),
- C0 = sha_init(),
- C1 = sha_update(C0, srp_pad_to(PadLength, UserPublic)),
- C2 = sha_update(C1, srp_pad_to(PadLength, HostPublic)),
- sha_final(C2);
+ C0 = hash_init(sha),
+ C1 = hash_update(C0, srp_pad_to(PadLength, UserPublic)),
+ C2 = hash_update(C1, srp_pad_to(PadLength, HostPublic)),
+ hash_final(C2);
srp_scrambler('3', _, HostPublic, _Prime) ->
%% The parameter u is a 32-bit unsigned integer which takes its value
%% from the first 32 bits of the SHA1 hash of B, MSB first.
@@ -1515,13 +1154,13 @@ srp_value_B_nif(_Multiplier, _Verifier, _Generator, _Exponent, _Prime) -> ?nif_s
%% Digital signatures --------------------------------------------------------------------
-rsa_sign_nif(_Type,_Data,_Key) -> ?nif_stub.
-dss_sign_nif(_Type,_Data,_Key) -> ?nif_stub.
-ecdsa_sign_nif(_Type, _DataOrDigest, _Curve, _Key) -> ?nif_stub.
+rsa_sign_nif(_Type,_Digest,_Key) -> ?nif_stub.
+dss_sign_nif(_Type,_Digest,_Key) -> ?nif_stub.
+ecdsa_sign_nif(_Type, _Digest, _Curve, _Key) -> ?nif_stub.
-dss_verify_nif(_Type, _Data, _Signature, _Key) -> ?nif_stub.
-rsa_verify_nif(_Type, _Data, _Signature, _Key) -> ?nif_stub.
-ecdsa_verify_nif(_Type, _DataOrDigest, _Signature, _Curve, _Key) -> ?nif_stub.
+dss_verify_nif(_Type, _Digest, _Signature, _Key) -> ?nif_stub.
+rsa_verify_nif(_Type, _Digest, _Signature, _Key) -> ?nif_stub.
+ecdsa_verify_nif(_Type, _Digest, _Signature, _Curve, _Key) -> ?nif_stub.
%% Public Keys --------------------------------------------------------------------
%% DH Diffie-Hellman functions
diff --git a/lib/debugger/src/dbg_iload.erl b/lib/debugger/src/dbg_iload.erl
index 7746a06fcb..369b456524 100644
--- a/lib/debugger/src/dbg_iload.erl
+++ b/lib/debugger/src/dbg_iload.erl
@@ -39,7 +39,7 @@
%% dbg_iserver. We are suspended until the module has been loaded.
%%--------------------------------------------------------------------
-spec load_mod(Mod, file:filename(), binary(), ets:tid()) ->
- {'ok', Mod} when is_subtype(Mod, atom()).
+ {'ok', Mod} when Mod :: atom().
load_mod(Mod, File, Binary, Db) ->
Flag = process_flag(trap_exit, true),
diff --git a/lib/debugger/test/map_SUITE.erl b/lib/debugger/test/map_SUITE.erl
index 0ef634f7aa..eabcdcbf42 100644
--- a/lib/debugger/test/map_SUITE.erl
+++ b/lib/debugger/test/map_SUITE.erl
@@ -2219,7 +2219,7 @@ map_guard_sequence_mixed(K1,K2,M) ->
t_frequency_table(Config) when is_list(Config) ->
- random:seed({13,1337,54}), % pseudo random
+ rand:seed(exsplus, {13,1337,54}), % pseudo random
N = 1000,
Ts = rand_terms(N),
#{ n:=N, tf := Tf } = frequency_table(Ts,#{ n=>0, tf => #{}}),
@@ -2262,7 +2262,7 @@ rand_terms(0) -> [];
rand_terms(N) -> [rand_term()|rand_terms(N-1)].
rand_term() ->
- case random:uniform(6) of
+ case rand:uniform(6) of
1 -> rand_binary();
2 -> rand_number();
3 -> rand_atom();
@@ -2272,21 +2272,21 @@ rand_term() ->
end.
rand_binary() ->
- case random:uniform(3) of
+ case rand:uniform(3) of
1 -> <<>>;
2 -> <<"hi">>;
3 -> <<"message text larger than 64 bytes. yep, message text larger than 64 bytes.">>
end.
rand_number() ->
- case random:uniform(3) of
- 1 -> random:uniform(5);
- 2 -> float(random:uniform(5));
- 3 -> 1 bsl (63 + random:uniform(3))
+ case rand:uniform(3) of
+ 1 -> rand:uniform(5);
+ 2 -> float(rand:uniform(5));
+ 3 -> 1 bsl (63 + rand:uniform(3))
end.
rand_atom() ->
- case random:uniform(3) of
+ case rand:uniform(3) of
1 -> hi;
2 -> some_atom;
3 -> some_other_atom
@@ -2294,21 +2294,21 @@ rand_atom() ->
rand_tuple() ->
- case random:uniform(3) of
+ case rand:uniform(3) of
1 -> {ok, rand_term()}; % careful
2 -> {1, 2, 3};
3 -> {<<"yep">>, 1337}
end.
rand_list() ->
- case random:uniform(3) of
+ case rand:uniform(3) of
1 -> "hi";
2 -> [1,rand_term()]; % careful
3 -> [improper|list]
end.
rand_map() ->
- case random:uniform(3) of
+ case rand:uniform(3) of
1 -> #{ hi => 3 };
2 -> #{ wat => rand_term(), other => 3 }; % careful
3 -> #{ hi => 42, other => 42, yet_anoter => 1337 }
diff --git a/lib/dialyzer/src/dialyzer_contracts.erl b/lib/dialyzer/src/dialyzer_contracts.erl
index 7251de8b10..83b3ef72f2 100644
--- a/lib/dialyzer/src/dialyzer_contracts.erl
+++ b/lib/dialyzer/src/dialyzer_contracts.erl
@@ -126,13 +126,19 @@ butlast([H|T]) -> [H|butlast(T)].
constraints_to_string([]) ->
"";
-constraints_to_string([{type, _, constraint, [{atom, _, What}, Types]}]) ->
- atom_to_list(What) ++ "(" ++
- sequence([erl_types:t_form_to_string(T) || T <- Types], ",") ++ ")";
constraints_to_string([{type, _, constraint, [{atom, _, What}, Types]}|Rest]) ->
- atom_to_list(What) ++ "(" ++
- sequence([erl_types:t_form_to_string(T) || T <- Types], ",")
- ++ "), " ++ constraints_to_string(Rest).
+ S = constraint_to_string(What, Types),
+ case Rest of
+ [] -> S;
+ _ -> S ++ ", " ++ constraints_to_string(Rest)
+ end.
+
+constraint_to_string(is_subtype, [{var, _, Var}, T]) ->
+ atom_to_list(Var) ++ " :: " ++ erl_types:t_form_to_string(T);
+constraint_to_string(What, Types) ->
+ atom_to_list(What) ++ "("
+ ++ sequence([erl_types:t_form_to_string(T) || T <- Types], ",")
+ ++ ")".
sequence([], _Delimiter) -> "";
sequence([H], _Delimiter) -> H;
diff --git a/lib/dialyzer/test/r9c_SUITE_data/results/mnesia b/lib/dialyzer/test/r9c_SUITE_data/results/mnesia
index 1dc5a105bf..220b18ca7a 100644
--- a/lib/dialyzer/test/r9c_SUITE_data/results/mnesia
+++ b/lib/dialyzer/test/r9c_SUITE_data/results/mnesia
@@ -6,7 +6,7 @@ mnesia_bup.erl:111: The created fun has no local return
mnesia_bup.erl:574: Function fallback_receiver/2 has no local return
mnesia_bup.erl:967: Function uninstall_fallback_master/2 has no local return
mnesia_checkpoint.erl:1014: The variable Error can never match since previous clauses completely covered the type {'ok',#checkpoint_args{nodes::[any()],retainers::[any(),...]}}
-mnesia_checkpoint.erl:894: The call sys:handle_system_msg(Msg::any(),From::any(),'no_parent','mnesia_checkpoint',[],Cp::#checkpoint_args{}) breaks the contract (Msg,From,Parent,Module,Debug,Misc) -> no_return() when is_subtype(Msg,term()), is_subtype(From,{pid(),Tag::_}), is_subtype(Parent,pid()), is_subtype(Module,module()), is_subtype(Debug,[dbg_opt()]), is_subtype(Misc,term())
+mnesia_checkpoint.erl:894: The call sys:handle_system_msg(Msg::any(),From::any(),'no_parent','mnesia_checkpoint',[],Cp::#checkpoint_args{}) breaks the contract (Msg,From,Parent,Module,Debug,Misc) -> no_return() when Msg :: term(), From :: {pid(),Tag::_}, Parent :: pid(), Module :: module(), Debug :: [dbg_opt()], Misc :: term()
mnesia_controller.erl:1666: The variable Tab can never match since previous clauses completely covered the type [any()]
mnesia_controller.erl:1679: The pattern {'stop', Reason, Reply, State2} can never match the type {'noreply',_} | {'reply',_,_} | {'stop','shutdown',#state{}}
mnesia_controller.erl:1685: The pattern {'noreply', State2, _Timeout} can never match the type {'reply',_,_}
diff --git a/lib/dialyzer/test/small_SUITE_data/results/contracts_with_subtypes b/lib/dialyzer/test/small_SUITE_data/results/contracts_with_subtypes
index a9fbfb6068..d2a3ebb766 100644
--- a/lib/dialyzer/test/small_SUITE_data/results/contracts_with_subtypes
+++ b/lib/dialyzer/test/small_SUITE_data/results/contracts_with_subtypes
@@ -1,15 +1,15 @@
-contracts_with_subtypes.erl:106: The call contracts_with_subtypes:rec_arg({'a','b'}) breaks the contract (Arg) -> 'ok' when is_subtype(Arg,{'a',A} | {'b',B}), is_subtype(A,'a' | {'b',B}), is_subtype(B,'b' | {'a',A})
-contracts_with_subtypes.erl:107: The call contracts_with_subtypes:rec_arg({'b','a'}) breaks the contract (Arg) -> 'ok' when is_subtype(Arg,{'a',A} | {'b',B}), is_subtype(A,'a' | {'b',B}), is_subtype(B,'b' | {'a',A})
-contracts_with_subtypes.erl:109: The call contracts_with_subtypes:rec_arg({'b',{'a','b'}}) breaks the contract (Arg) -> 'ok' when is_subtype(Arg,{'a',A} | {'b',B}), is_subtype(A,'a' | {'b',B}), is_subtype(B,'b' | {'a',A})
-contracts_with_subtypes.erl:135: The call contracts_with_subtypes:rec2({'a','b'}) breaks the contract (Arg) -> 'ok' when is_subtype(Arg,ab())
-contracts_with_subtypes.erl:136: The call contracts_with_subtypes:rec2({'b','a'}) breaks the contract (Arg) -> 'ok' when is_subtype(Arg,ab())
-contracts_with_subtypes.erl:137: The call contracts_with_subtypes:rec2({'a',{'b','a'}}) breaks the contract (Arg) -> 'ok' when is_subtype(Arg,ab())
-contracts_with_subtypes.erl:138: The call contracts_with_subtypes:rec2({'b',{'a','b'}}) breaks the contract (Arg) -> 'ok' when is_subtype(Arg,ab())
-contracts_with_subtypes.erl:139: The call contracts_with_subtypes:rec2({'a',{'b',{'a','b'}}}) breaks the contract (Arg) -> 'ok' when is_subtype(Arg,ab())
-contracts_with_subtypes.erl:140: The call contracts_with_subtypes:rec2({'b',{'a',{'b','a'}}}) breaks the contract (Arg) -> 'ok' when is_subtype(Arg,ab())
-contracts_with_subtypes.erl:141: The call contracts_with_subtypes:rec2({'a',{'b',{'a',{'b','a'}}}}) breaks the contract (Arg) -> 'ok' when is_subtype(Arg,ab())
-contracts_with_subtypes.erl:142: The call contracts_with_subtypes:rec2({'b',{'a',{'b',{'a','b'}}}}) breaks the contract (Arg) -> 'ok' when is_subtype(Arg,ab())
+contracts_with_subtypes.erl:106: The call contracts_with_subtypes:rec_arg({'a','b'}) breaks the contract (Arg) -> 'ok' when Arg :: {'a',A} | {'b',B}, A :: 'a' | {'b',B}, B :: 'b' | {'a',A}
+contracts_with_subtypes.erl:107: The call contracts_with_subtypes:rec_arg({'b','a'}) breaks the contract (Arg) -> 'ok' when Arg :: {'a',A} | {'b',B}, A :: 'a' | {'b',B}, B :: 'b' | {'a',A}
+contracts_with_subtypes.erl:109: The call contracts_with_subtypes:rec_arg({'b',{'a','b'}}) breaks the contract (Arg) -> 'ok' when Arg :: {'a',A} | {'b',B}, A :: 'a' | {'b',B}, B :: 'b' | {'a',A}
+contracts_with_subtypes.erl:135: The call contracts_with_subtypes:rec2({'a','b'}) breaks the contract (Arg) -> 'ok' when Arg :: ab()
+contracts_with_subtypes.erl:136: The call contracts_with_subtypes:rec2({'b','a'}) breaks the contract (Arg) -> 'ok' when Arg :: ab()
+contracts_with_subtypes.erl:137: The call contracts_with_subtypes:rec2({'a',{'b','a'}}) breaks the contract (Arg) -> 'ok' when Arg :: ab()
+contracts_with_subtypes.erl:138: The call contracts_with_subtypes:rec2({'b',{'a','b'}}) breaks the contract (Arg) -> 'ok' when Arg :: ab()
+contracts_with_subtypes.erl:139: The call contracts_with_subtypes:rec2({'a',{'b',{'a','b'}}}) breaks the contract (Arg) -> 'ok' when Arg :: ab()
+contracts_with_subtypes.erl:140: The call contracts_with_subtypes:rec2({'b',{'a',{'b','a'}}}) breaks the contract (Arg) -> 'ok' when Arg :: ab()
+contracts_with_subtypes.erl:141: The call contracts_with_subtypes:rec2({'a',{'b',{'a',{'b','a'}}}}) breaks the contract (Arg) -> 'ok' when Arg :: ab()
+contracts_with_subtypes.erl:142: The call contracts_with_subtypes:rec2({'b',{'a',{'b',{'a','b'}}}}) breaks the contract (Arg) -> 'ok' when Arg :: ab()
contracts_with_subtypes.erl:175: The pattern 1 can never match the type string()
contracts_with_subtypes.erl:178: The pattern 'alpha' can never match the type {'ok',_} | {'ok',_,string()}
contracts_with_subtypes.erl:180: The pattern 42 can never match the type {'ok',_} | {'ok',_,string()}
@@ -24,13 +24,13 @@ contracts_with_subtypes.erl:23: Invalid type specification for function contract
contracts_with_subtypes.erl:240: The pattern {'ok', 42} can never match the type {'ok',_,string()}
contracts_with_subtypes.erl:241: The pattern 42 can never match the type {'ok',_,string()}
contracts_with_subtypes.erl:267: Function flat_ets_new_t/0 has no local return
-contracts_with_subtypes.erl:268: The call contracts_with_subtypes:flat_ets_new(12,[]) breaks the contract (Name,Options) -> atom() when is_subtype(Name,atom()), is_subtype(Options,[Option]), is_subtype(Option,'set' | 'ordered_set' | 'bag' | 'duplicate_bag' | 'public' | 'protected' | 'private' | 'named_table' | {'keypos',integer()} | {'heir',pid(),term()} | {'heir','none'} | {'write_concurrency',boolean()} | {'read_concurrency',boolean()} | 'compressed')
+contracts_with_subtypes.erl:268: The call contracts_with_subtypes:flat_ets_new(12,[]) breaks the contract (Name,Options) -> atom() when Name :: atom(), Options :: [Option], Option :: 'set' | 'ordered_set' | 'bag' | 'duplicate_bag' | 'public' | 'protected' | 'private' | 'named_table' | {'keypos',integer()} | {'heir',pid(),term()} | {'heir','none'} | {'write_concurrency',boolean()} | {'read_concurrency',boolean()} | 'compressed'
contracts_with_subtypes.erl:294: Function factored_ets_new_t/0 has no local return
-contracts_with_subtypes.erl:295: The call contracts_with_subtypes:factored_ets_new(12,[]) breaks the contract (Name,Options) -> atom() when is_subtype(Name,atom()), is_subtype(Options,[Option]), is_subtype(Option,Type | Access | 'named_table' | {'keypos',Pos} | {'heir',Pid::pid(),HeirData} | {'heir','none'} | Tweaks), is_subtype(Type,type()), is_subtype(Access,access()), is_subtype(Tweaks,{'write_concurrency',boolean()} | {'read_concurrency',boolean()} | 'compressed'), is_subtype(Pos,pos_integer()), is_subtype(HeirData,term())
-contracts_with_subtypes.erl:77: The call contracts_with_subtypes:foo1(5) breaks the contract (Arg1) -> Res when is_subtype(Arg1,atom()), is_subtype(Res,atom())
-contracts_with_subtypes.erl:78: The call contracts_with_subtypes:foo2(5) breaks the contract (Arg1) -> Res when is_subtype(Arg1,Arg2), is_subtype(Arg2,atom()), is_subtype(Res,atom())
-contracts_with_subtypes.erl:79: The call contracts_with_subtypes:foo3(5) breaks the contract (Arg1) -> Res when is_subtype(Arg2,atom()), is_subtype(Arg1,Arg2), is_subtype(Res,atom())
+contracts_with_subtypes.erl:295: The call contracts_with_subtypes:factored_ets_new(12,[]) breaks the contract (Name,Options) -> atom() when Name :: atom(), Options :: [Option], Option :: Type | Access | 'named_table' | {'keypos',Pos} | {'heir',Pid::pid(),HeirData} | {'heir','none'} | Tweaks, Type :: type(), Access :: access(), Tweaks :: {'write_concurrency',boolean()} | {'read_concurrency',boolean()} | 'compressed', Pos :: pos_integer(), HeirData :: term()
+contracts_with_subtypes.erl:77: The call contracts_with_subtypes:foo1(5) breaks the contract (Arg1) -> Res when Arg1 :: atom(), Res :: atom()
+contracts_with_subtypes.erl:78: The call contracts_with_subtypes:foo2(5) breaks the contract (Arg1) -> Res when Arg1 :: Arg2, Arg2 :: atom(), Res :: atom()
+contracts_with_subtypes.erl:79: The call contracts_with_subtypes:foo3(5) breaks the contract (Arg1) -> Res when Arg2 :: atom(), Arg1 :: Arg2, Res :: atom()
contracts_with_subtypes.erl:7: Invalid type specification for function contracts_with_subtypes:extract/0. The success typing is () -> 'something'
-contracts_with_subtypes.erl:80: The call contracts_with_subtypes:foo4(5) breaks the contract (Type) -> Type when is_subtype(Type,atom())
+contracts_with_subtypes.erl:80: The call contracts_with_subtypes:foo4(5) breaks the contract (Type) -> Type when Type :: atom()
contracts_with_subtypes.erl:81: The call contracts_with_subtypes:foo5(5) breaks the contract (Type::atom()) -> Type::atom()
-contracts_with_subtypes.erl:82: The call contracts_with_subtypes:foo6(5) breaks the contract (Type) -> Type when is_subtype(Type,atom())
+contracts_with_subtypes.erl:82: The call contracts_with_subtypes:foo6(5) breaks the contract (Type) -> Type when Type :: atom()
diff --git a/lib/dialyzer/test/small_SUITE_data/results/contracts_with_subtypes2 b/lib/dialyzer/test/small_SUITE_data/results/contracts_with_subtypes2
index 9f5433a13d..1a8aeb13d0 100644
--- a/lib/dialyzer/test/small_SUITE_data/results/contracts_with_subtypes2
+++ b/lib/dialyzer/test/small_SUITE_data/results/contracts_with_subtypes2
@@ -1,3 +1,3 @@
contracts_with_subtypes2.erl:18: Function t/0 has no local return
-contracts_with_subtypes2.erl:19: The call contracts_with_subtypes2:t({'a',{'b',{'c',{'d',{'e',{'g',3}}}}}}) breaks the contract (Arg) -> 'ok' when is_subtype(Arg,{'a',A}), is_subtype(A,{'b',B}), is_subtype(B,{'c',C}), is_subtype(C,{'d',D}), is_subtype(D,{'e',E}), is_subtype(E,{'f',_})
+contracts_with_subtypes2.erl:19: The call contracts_with_subtypes2:t({'a',{'b',{'c',{'d',{'e',{'g',3}}}}}}) breaks the contract (Arg) -> 'ok' when Arg :: {'a',A}, A :: {'b',B}, B :: {'c',C}, C :: {'d',D}, D :: {'e',E}, E :: {'f',_}
diff --git a/lib/dialyzer/test/small_SUITE_data/results/pretty_bitstring b/lib/dialyzer/test/small_SUITE_data/results/pretty_bitstring
index 0ad6eee766..e148e5cf22 100644
--- a/lib/dialyzer/test/small_SUITE_data/results/pretty_bitstring
+++ b/lib/dialyzer/test/small_SUITE_data/results/pretty_bitstring
@@ -1,3 +1,3 @@
pretty_bitstring.erl:7: Function t/0 has no local return
-pretty_bitstring.erl:8: The call binary:copy(#{#<1>(8, 1, 'integer', ['unsigned', 'big']), #<2>(8, 1, 'integer', ['unsigned', 'big']), #<3>(3, 1, 'integer', ['unsigned', 'big'])}#,2) breaks the contract (Subject,N) -> binary() when is_subtype(Subject,binary()), is_subtype(N,non_neg_integer())
+pretty_bitstring.erl:8: The call binary:copy(#{#<1>(8, 1, 'integer', ['unsigned', 'big']), #<2>(8, 1, 'integer', ['unsigned', 'big']), #<3>(3, 1, 'integer', ['unsigned', 'big'])}#,2) breaks the contract (Subject,N) -> binary() when Subject :: binary(), N :: non_neg_integer()
diff --git a/lib/dialyzer/test/user_SUITE_data/results/wsp_pdu b/lib/dialyzer/test/user_SUITE_data/results/wsp_pdu
index d1f8f4caf2..626e677524 100644
--- a/lib/dialyzer/test/user_SUITE_data/results/wsp_pdu
+++ b/lib/dialyzer/test/user_SUITE_data/results/wsp_pdu
@@ -6,7 +6,7 @@ wsp_pdu.erl:2403: The call wsp_pdu:d_date(Data1::binary()) will never return sin
wsp_pdu.erl:2406: Guard test is_integer(Sec::{[byte()] | byte() | {'long',binary()} | {'short',binary()},binary()}) can never succeed
wsp_pdu.erl:2408: The pattern {'short', Data2} can never match the type {[byte()] | byte() | {'long',binary()} | {'short',binary()},binary()}
wsp_pdu.erl:2755: Function parse_push_flag/1 has no local return
-wsp_pdu.erl:2756: The call erlang:integer_to_list(Value::[any()]) breaks the contract (Integer) -> string() when is_subtype(Integer,integer())
+wsp_pdu.erl:2756: The call erlang:integer_to_list(Value::[any()]) breaks the contract (Integer) -> string() when Integer :: integer()
wsp_pdu.erl:2875: The call wsp_pdu:d_text_string(Data::byte()) will never return since it differs in the 1st argument from the success typing arguments: (binary())
wsp_pdu.erl:2976: The call wsp_pdu:d_q_value(QData::byte()) will never return since it differs in the 1st argument from the success typing arguments: (<<_:8,_:_*8>>)
wsp_pdu.erl:3336: The call wsp_pdu:encode_typed_field(Ver::any(),'Q-value',ParamValue::any()) will never return since it differs in the 2nd argument from the success typing arguments: (any(),'Constrained-encoding' | 'Date-value' | 'No-value' | 'Short-integer' | 'Text-string' | 'Text-value' | 'Well-known-charset',any())
diff --git a/lib/diameter/src/base/diameter_traffic.erl b/lib/diameter/src/base/diameter_traffic.erl
index 9e14860693..07f39c562f 100644
--- a/lib/diameter/src/base/diameter_traffic.erl
+++ b/lib/diameter/src/base/diameter_traffic.erl
@@ -169,7 +169,7 @@ incr_error(Dir, Id, TPid, _) ->
incr_error(Dir, Id, TPid) ->
incr(TPid, {Id, Dir, error}).
-
+
%% ---------------------------------------------------------------------------
%% incr_rc/4
%% ---------------------------------------------------------------------------
@@ -1485,16 +1485,12 @@ send_R(Pkt0,
caps = Caps,
packet = Pkt0},
- try
- incr(send, Pkt, TPid, AppDict),
- TRef = send_request(TPid, Pkt, Req, SvcName, Timeout),
- Pid ! Ref, %% tell caller a send has been attempted
- handle_answer(SvcName,
- App,
- recv_A(Timeout, SvcName, App, Opts, {TRef, Req}))
- after
- erase_requests(Pkt)
- end.
+ incr(send, Pkt, TPid, AppDict),
+ TRef = send_request(TPid, Pkt, Req, SvcName, Timeout),
+ Pid ! Ref, %% tell caller a send has been attempted
+ handle_answer(SvcName,
+ App,
+ recv_A(Timeout, SvcName, App, Opts, {TRef, Req})).
%% recv_A/5
@@ -1694,9 +1690,18 @@ encode(_, _, #diameter_packet{} = Pkt) ->
send_request(TPid, #diameter_packet{bin = Bin} = Pkt, Req, _SvcName, Timeout)
when node() == node(TPid) ->
- %% Store the outgoing request before sending to avoid a race with
- %% reply reception.
- TRef = store_request(TPid, Bin, Req, Timeout),
+ Seqs = diameter_codec:sequence_numbers(Bin),
+ TRef = erlang:start_timer(Timeout, self(), TPid),
+ Entry = {Seqs, Req, TRef},
+
+ %% Ensure that request table is cleaned even if we receive an exit
+ %% signal. An alternative would be to simply trap exits, but
+ %% callbacks are applied in this process, and these could possibly
+ %% be expecting the prevailing behaviour.
+ Self = self(),
+ spawn(fun() -> diameter_lib:wait([Self]), erase_request(Entry) end),
+
+ store_request(Entry, TPid),
send(TPid, Pkt),
TRef;
@@ -1711,31 +1716,21 @@ send_request(TPid, #diameter_packet{} = Pkt, Req, SvcName, Timeout) ->
%% send/1
send({TPid, Pkt, #request{handler = Pid} = Req0, SvcName, Timeout, TRef}) ->
- Seqs = diameter_codec:sequence_numbers(Pkt),
Req = Req0#request{handler = self()},
- Ref = send_request(TPid, Pkt, Req, SvcName, Timeout),
-
- try
- recv(TPid, Pid, TRef, Ref)
- after
- %% Remove only the entry for this specific send since a resend
- %% from the originating node can pick another transport on
- %% this one.
- ets:delete_object(?REQUEST_TABLE, {Seqs, Req, Ref})
- end.
+ recv(TPid, Pid, TRef, send_request(TPid, Pkt, Req, SvcName, Timeout)).
%% recv/4
%%
%% Relay an answer from a remote node.
-recv(TPid, Pid, TRef, Ref) ->
+recv(TPid, Pid, TRef, LocalTRef) ->
receive
{answer, _, _, _, _} = A ->
Pid ! A;
- {failover = T, Ref} ->
+ {failover = T, LocalTRef} ->
Pid ! {T, TRef};
T ->
- exit({timeout, Ref, TPid} = T)
+ exit({timeout, LocalTRef, TPid} = T)
end.
%% send/2
@@ -1812,17 +1807,21 @@ resend_request(Pkt0,
TRef = send_request(TPid, Pkt, Req, SvcName, Tmo),
{TRef, Req}.
-%% store_request/4
+%% store_request/2
-store_request(TPid, Bin, Req, Timeout) ->
- Seqs = diameter_codec:sequence_numbers(Bin),
- TRef = erlang:start_timer(Timeout, self(), TPid),
- ets:insert(?REQUEST_TABLE, {Seqs, Req, TRef}),
+store_request(T, TPid) ->
+ ets:insert(?REQUEST_TABLE, T),
ets:member(?REQUEST_TABLE, TPid)
- orelse (self() ! {failover, TRef}), %% failover/1 may have missed
- TRef.
+ orelse begin
+ {_Seqs, _Req, TRef} = T,
+ (self() ! {failover, TRef}) %% failover/1 may have missed
+ end.
%% lookup_request/2
+%%
+%% Note the match on both the key and transport pid. The latter is
+%% necessary since the same Hop-by-Hop and End-to-End identifiers are
+%% reused in the case of retransmission.
lookup_request(Msg, TPid) ->
Seqs = diameter_codec:sequence_numbers(Msg),
@@ -1836,10 +1835,10 @@ lookup_request(Msg, TPid) ->
false
end.
-%% erase_requests/1
+%% erase_request/1
-erase_requests(Pkt) ->
- ets:delete(?REQUEST_TABLE, diameter_codec:sequence_numbers(Pkt)).
+erase_request(T) ->
+ ets:delete_object(?REQUEST_TABLE, T).
%% match_requests/1
@@ -1862,7 +1861,7 @@ failover(TPid)
when is_pid(TPid) ->
lists:foreach(fun failover/1, match_requests(TPid));
%% Note that a request process can store its request after failover
-%% notifications are sent here: store_request/4 sends the notification
+%% notifications are sent here: store_request/2 sends the notification
%% in that case.
%% Failover as a consequence of request_peer_down/1: inform the
diff --git a/lib/diameter/src/diameter.appup.src b/lib/diameter/src/diameter.appup.src
index b77043d983..ddde648e08 100644
--- a/lib/diameter/src/diameter.appup.src
+++ b/lib/diameter/src/diameter.appup.src
@@ -60,7 +60,8 @@
{load_module, diameter_gen_acct_rfc6733},
{load_module, diameter_gen_base_rfc3588},
{load_module, diameter_gen_base_accounting},
- {load_module, diameter_gen_relay}]}
+ {load_module, diameter_gen_relay}]},
+ {"1.11", [{load_module, diameter_traffic}]} %% 18.1
],
[
{"0.9", [{restart_application, diameter}]},
@@ -102,6 +103,7 @@
{load_module, diameter_stats},
{load_module, diameter_watchdog},
{load_module, diameter_peer_fsm},
- {load_module, diameter_codec}]}
+ {load_module, diameter_codec}]},
+ {"1.11", [{load_module, diameter_traffic}]}
]
}.
diff --git a/lib/diameter/vsn.mk b/lib/diameter/vsn.mk
index 041d21b261..7ac4a7adfb 100644
--- a/lib/diameter/vsn.mk
+++ b/lib/diameter/vsn.mk
@@ -17,5 +17,5 @@
# %CopyrightEnd%
APPLICATION = diameter
-DIAMETER_VSN = 1.11
+DIAMETER_VSN = 1.11.1
APP_VSN = $(APPLICATION)-$(DIAMETER_VSN)$(PRE_VSN)
diff --git a/lib/erl_docgen/priv/dtd/cites.dtd b/lib/erl_docgen/priv/dtd/cites.dtd
index 73931af009..4558947db0 100644
--- a/lib/erl_docgen/priv/dtd/cites.dtd
+++ b/lib/erl_docgen/priv/dtd/cites.dtd
@@ -30,7 +30,7 @@
<!ELEMENT cite (id, shortdef, def, resp?) >
<!ELEMENT id (#PCDATA) >
<!ELEMENT shortdef (#PCDATA) >
-<!ELEMENT def (#PCDATA|c|em)* >
+<!ELEMENT def (#PCDATA|c|i|em)* >
<!ELEMENT resp (#PCDATA) >
<!ELEMENT c (#PCDATA) >
<!ELEMENT em (#PCDATA|c)* >
diff --git a/lib/erl_docgen/priv/dtd/common.dtd b/lib/erl_docgen/priv/dtd/common.dtd
index ded16d308f..961bcd3fc2 100644
--- a/lib/erl_docgen/priv/dtd/common.dtd
+++ b/lib/erl_docgen/priv/dtd/common.dtd
@@ -24,21 +24,23 @@
<!ENTITY % block "p|pre|code|list|taglist|codeinclude|
erleval" >
-<!ENTITY % inline "#PCDATA|c|em|term|cite|br|path|seealso|
- url|marker" >
+<!ENTITY % inline "#PCDATA|c|i|em|term|cite|br|path|seealso|
+ url|marker|anno" >
<!-- XXX -->
<!ELEMENT p (%inline;)* >
-<!ELEMENT pre (#PCDATA|seealso|url|input)* >
-<!ELEMENT input (#PCDATA|seealso|url)* >
-<!ELEMENT code (#PCDATA) >
+<!ELEMENT pre (#PCDATA|seealso|url|input|anno)* >
+<!ELEMENT input (#PCDATA|seealso|url|anno)* >
+<!ELEMENT code (#PCDATA|anno)* >
<!ATTLIST code type (erl|c|none) "none" >
<!ELEMENT quote (p)* >
<!ELEMENT warning (%block;|quote|br|marker)* >
<!ELEMENT note (%block;|quote|br|marker)* >
<!ELEMENT dont (%block;|quote|br|marker)* >
<!ELEMENT do (%block;|quote|br|marker)* >
-<!ELEMENT c (#PCDATA) >
-<!ELEMENT em (#PCDATA|c)* >
+<!ELEMENT c (#PCDATA|anno)* >
+<!ELEMENT i (#PCDATA|c|anno)* >
+<!ELEMENT em (#PCDATA|c|anno)* >
+<!ELEMENT anno (#PCDATA) >
<!-- XXX -->
<!ELEMENT term (termdef?) >
@@ -64,13 +66,13 @@
<!ELEMENT list (item+) >
<!ATTLIST list type (ordered|bulleted) "bulleted" >
-<!ELEMENT taglist (tag,item)+ >
-<!ELEMENT tag (#PCDATA|c|em|seealso|url|marker)* >
-<!ELEMENT item (%inline;|%block;)* >
+<!ELEMENT taglist (tag,item+)+ >
+<!ELEMENT tag (#PCDATA|c|i|em|br|seealso|url|marker|anno)* >
+<!ELEMENT item (%inline;|%block;|warning|note|dont|do)* >
<!-- References -->
-<!ELEMENT seealso (#PCDATA|c|em)* >
+<!ELEMENT seealso (#PCDATA|c|i|em|anno)* >
<!ATTLIST seealso marker CDATA #REQUIRED >
<!ELEMENT url (#PCDATA) >
<!ATTLIST url href CDATA #REQUIRED >
diff --git a/lib/erl_docgen/priv/dtd/common.header.dtd b/lib/erl_docgen/priv/dtd/common.header.dtd
index 71a8662572..eb27dc8f97 100644
--- a/lib/erl_docgen/priv/dtd/common.header.dtd
+++ b/lib/erl_docgen/priv/dtd/common.header.dtd
@@ -18,8 +18,8 @@
$Id$
-->
<!ELEMENT header (copyright?,legalnotice?,title,shorttitle?,
- prepared,responsible?,docno,approved?,
- checked?,date,rev,file?) >
+ prepared?,responsible?,docno?,approved?,
+ checked?,date?,rev?,file?) >
<!--
The titlestyle attribute is only defined to make all the book.xml files
diff --git a/lib/erl_docgen/priv/dtd/common.refs.dtd b/lib/erl_docgen/priv/dtd/common.refs.dtd
index f57e46a624..4f87007a09 100644
--- a/lib/erl_docgen/priv/dtd/common.refs.dtd
+++ b/lib/erl_docgen/priv/dtd/common.refs.dtd
@@ -27,21 +27,23 @@
<!ELEMENT description (%block;|quote|br|marker|warning|note|dont|do)* >
<!ELEMENT funcs (func)+ >
-<!ELEMENT func (name+,type_desc*,fsummary,type?,desc?) >
+<!ELEMENT func (name+,fsummary,(type|type_desc)*,desc?) >
<!-- ELEMENT name is defined in each ref dtd -->
-<!ELEMENT fsummary (#PCDATA|c|em)* >
+<!ELEMENT fsummary (#PCDATA|c|i|em|anno)* >
<!ELEMENT type (v,d?)* >
<!ATTLIST type variable CDATA #IMPLIED
+ name CDATA #IMPLIED
name_i CDATA #IMPLIED>
-<!ELEMENT v (#PCDATA) >
-<!ELEMENT d (#PCDATA|c|em)* >
-<!ELEMENT desc (%block;|quote|br|marker|warning|note|dont|do|anno)* >
+<!ELEMENT v (#PCDATA|seealso)* >
+<!ELEMENT d (#PCDATA|seealso|c|i|em)* >
+<!ELEMENT desc (%block;|quote|br|marker|warning|note|dont|do)* >
<!ELEMENT authors (aname,email)+ >
<!ELEMENT aname (#PCDATA) >
<!ELEMENT email (#PCDATA) >
<!ELEMENT section (marker*,title,(%block;|quote|br|marker|
- warning|note|dont|do)*) >
+ warning|note|dont|do|section)*) >
<!ELEMENT datatypes (datatype)+ >
<!ELEMENT datatype (name+,desc?) >
-<!ELEMENT type_desc (#PCDATA) >
-<!ATTLIST type_desc variable CDATA #REQUIRED>
+<!ELEMENT type_desc (#PCDATA|anno|c|seealso)* >
+<!ATTLIST type_desc variable CDATA #IMPLIED
+ name CDATA #IMPLIED>
diff --git a/lib/erl_docgen/priv/dtd/erlref.dtd b/lib/erl_docgen/priv/dtd/erlref.dtd
index d62e2a5fcb..835407520a 100644
--- a/lib/erl_docgen/priv/dtd/erlref.dtd
+++ b/lib/erl_docgen/priv/dtd/erlref.dtd
@@ -32,4 +32,5 @@
<!ELEMENT name (#PCDATA) >
<!ATTLIST name name CDATA #IMPLIED
arity CDATA #IMPLIED
- clause_i CDATA #IMPLIED>
+ clause_i CDATA #IMPLIED
+ n_vars CDATA #IMPLIED>
diff --git a/lib/erl_docgen/priv/dtd/terms.dtd b/lib/erl_docgen/priv/dtd/terms.dtd
index fd160b5c02..c2965eb61c 100644
--- a/lib/erl_docgen/priv/dtd/terms.dtd
+++ b/lib/erl_docgen/priv/dtd/terms.dtd
@@ -30,7 +30,7 @@
<!ELEMENT term (id, shortdef, def, resp?) >
<!ELEMENT id (#PCDATA) >
<!ELEMENT shortdef (#PCDATA) >
-<!ELEMENT def (#PCDATA|c|em)* >
+<!ELEMENT def (#PCDATA|c|i|em)* >
<!ELEMENT resp (#PCDATA) >
<!ELEMENT c (#PCDATA) >
<!ELEMENT em (#PCDATA|c)* >
diff --git a/lib/erl_docgen/priv/xsl/db_html.xsl b/lib/erl_docgen/priv/xsl/db_html.xsl
index f5ddd364d3..c2325fbee9 100644
--- a/lib/erl_docgen/priv/xsl/db_html.xsl
+++ b/lib/erl_docgen/priv/xsl/db_html.xsl
@@ -990,12 +990,15 @@
</p>
</xsl:template>
-
<!-- Inline elements -->
<xsl:template match="b">
<strong><xsl:apply-templates/></strong>
</xsl:template>
+ <xsl:template match="i">
+ <i><xsl:apply-templates/></i>
+ </xsl:template>
+
<xsl:template match="br">
<br/>
</xsl:template>
diff --git a/lib/erl_docgen/priv/xsl/db_man.xsl b/lib/erl_docgen/priv/xsl/db_man.xsl
index 120bf9880d..5201465e42 100644
--- a/lib/erl_docgen/priv/xsl/db_man.xsl
+++ b/lib/erl_docgen/priv/xsl/db_man.xsl
@@ -595,6 +595,12 @@
<xsl:text>\fR\&amp; </xsl:text>
</xsl:template>
+ <xsl:template match="i">
+ <xsl:text>\fI</xsl:text>
+ <xsl:apply-templates/>
+ <xsl:text>\fR\&amp; </xsl:text>
+ </xsl:template>
+
<xsl:template match="br">
<xsl:choose>
<xsl:when test="ancestor::head">
diff --git a/lib/erl_docgen/priv/xsl/db_pdf.xsl b/lib/erl_docgen/priv/xsl/db_pdf.xsl
index 53e202d52c..37a2d55274 100644
--- a/lib/erl_docgen/priv/xsl/db_pdf.xsl
+++ b/lib/erl_docgen/priv/xsl/db_pdf.xsl
@@ -1186,6 +1186,12 @@
</fo:inline>
</xsl:template>
+ <xsl:template match="i">
+ <fo:inline font-weight="italic">
+ <xsl:apply-templates/>
+ </fo:inline>
+ </xsl:template>
+
<xsl:template match="br">
<fo:block/>
</xsl:template>
diff --git a/lib/erl_docgen/src/docgen_edoc_xml_cb.erl b/lib/erl_docgen/src/docgen_edoc_xml_cb.erl
index 03fc161c5a..0ac7985a48 100644
--- a/lib/erl_docgen/src/docgen_edoc_xml_cb.erl
+++ b/lib/erl_docgen/src/docgen_edoc_xml_cb.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2015. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -352,8 +352,8 @@ otp_xmlify_e(#xmlElement{name=code} = E) -> % 4)
end;
otp_xmlify_e(#xmlElement{name=Tag} = E) % 5a
when Tag==h1; Tag==h2; Tag==h3; Tag==h4; Tag==h5 ->
- Content = text_and_a_name_only(E#xmlElement.content),
- [E#xmlElement{name=b, content=Content}];
+ {Name, Text} = text_and_a_name_only(E#xmlElement.content),
+ [Name, E#xmlElement{name=b, content=Text}];
otp_xmlify_e(#xmlElement{name=Tag} = E) % 5b-c)
when Tag==center;
Tag==font ->
@@ -1190,17 +1190,13 @@ get_text(#xmlElement{content=[#xmlText{value=Text}]}) ->
get_text(#xmlElement{content=[E]}) ->
get_text(E).
-%% text_and_name_only(Es) -> Ts
-text_and_a_name_only([#xmlElement{
- name = a,
- attributes = [#xmlAttribute{name=name}]} = Name|Es]) ->
- [Name|text_and_a_name_only(Es)];
-text_and_a_name_only([#xmlElement{content = Content}|Es]) ->
- text_and_a_name_only(Content) ++ text_and_a_name_only(Es);
-text_and_a_name_only([#xmlText{} = E |Es]) ->
- [E | text_and_a_name_only(Es)];
-text_and_a_name_only([]) ->
- [].
+%% text_and_name_only(Es) -> {N, Ts}
+text_and_a_name_only(Es) ->
+ [Name|_] = [Name ||
+ #xmlElement{
+ name = a,
+ attributes = [#xmlAttribute{name=name}]}=Name <- Es],
+ {Name#xmlElement{content = []}, text_only(Es)}.
%% text_only(Es) -> Ts
%% Takes a list of xmlElement and xmlText and return a lists of xmlText.
diff --git a/lib/erl_docgen/vsn.mk b/lib/erl_docgen/vsn.mk
index 2abd3d2b7e..43f5a570d7 100644
--- a/lib/erl_docgen/vsn.mk
+++ b/lib/erl_docgen/vsn.mk
@@ -1 +1 @@
-ERL_DOCGEN_VSN = 0.4
+ERL_DOCGEN_VSN = 0.4.1
diff --git a/lib/erl_interface/src/connect/ei_resolve.c b/lib/erl_interface/src/connect/ei_resolve.c
index 3f1be2b17d..6381b02393 100644
--- a/lib/erl_interface/src/connect/ei_resolve.c
+++ b/lib/erl_interface/src/connect/ei_resolve.c
@@ -601,6 +601,16 @@ struct hostent *ei_gethostbyaddr(const char *addr, int len, int type)
return gethostbyaddr(addr, len, type);
}
+/*
+ * Imprecise way to select the actually available gethostbyname_r and
+ * gethostbyaddr_r.
+ *
+ * TODO: check this properly in configure.in
+ */
+#if (defined(__linux__) || (__FreeBSD_version >= 602000) || defined(__DragonFly__))
+ #define HAVE_GETHOSTBYADDR_R_8 1
+#endif
+
struct hostent *ei_gethostbyaddr_r(const char *addr,
int length,
int type,
@@ -616,7 +626,7 @@ struct hostent *ei_gethostbyaddr_r(const char *addr,
#ifndef HAVE_GETHOSTBYNAME_R
return my_gethostbyaddr_r(addr,length,type,hostp,buffer,buflen,h_errnop);
#else
-#if (defined(__GLIBC__) || (__FreeBSD_version >= 602000) || defined(__DragonFly__))
+#ifdef HAVE_GETHOSTBYADDR_R_8
struct hostent *result;
gethostbyaddr_r(addr, length, type, hostp, buffer, buflen, &result,
@@ -643,7 +653,7 @@ struct hostent *ei_gethostbyname_r(const char *name,
#ifndef HAVE_GETHOSTBYNAME_R
return my_gethostbyname_r(name,hostp,buffer,buflen,h_errnop);
#else
-#if (defined(__GLIBC__) || (__FreeBSD_version >= 602000) || defined(__DragonFly__) || defined(__ANDROID__))
+#ifdef HAVE_GETHOSTBYADDR_R_8
struct hostent *result;
gethostbyname_r(name, hostp, buffer, buflen, &result, h_errnop);
diff --git a/lib/eunit/doc/overview.edoc b/lib/eunit/doc/overview.edoc
index 2789a05792..12ea02f442 100644
--- a/lib/eunit/doc/overview.edoc
+++ b/lib/eunit/doc/overview.edoc
@@ -907,7 +907,6 @@ the test set is finished, regardless of the outcome (success, failures,
timeouts, etc.).
To make the descriptions simpler, we first list some definitions:
-<center>
<table border="0" cellspacing="4">
<tr>
<td>`Setup'</td><td>`() -> (R::any())'</td>
@@ -928,7 +927,6 @@ To make the descriptions simpler, we first list some definitions:
<td>`Where'</td><td>`local | spawn | {spawn, Node::atom()}'</td>
</tr>
</table>
-</center>
(these are explained in more detail further below.)
The following representations specify fixture handling for test sets:
diff --git a/lib/eunit/include/eunit.hrl b/lib/eunit/include/eunit.hrl
index 88e9d6c19b..8f678b0290 100644
--- a/lib/eunit/include/eunit.hrl
+++ b/lib/eunit/include/eunit.hrl
@@ -135,7 +135,6 @@
-define(_assertThrow(Term, Expr), ?_assertException(throw, Term, Expr)).
-define(_assertNotException(Class, Term, Expr),
?_test(?assertNotException(Class, Term, Expr))).
--define(_assertReceive(Guard, Expr), ?_test(?assertReceive(Guard, Expr))).
%% Macros for running operating system commands. (Note that these
%% require EUnit to be present at runtime, or at least eunit_lib.)
diff --git a/lib/gs/Makefile b/lib/gs/Makefile
index 02c8fc3467..b95d435461 100644
--- a/lib/gs/Makefile
+++ b/lib/gs/Makefile
@@ -26,7 +26,7 @@ include $(ERL_TOP)/make/$(TARGET)/otp.mk
# Macros
#
-SUB_DIRECTORIES = src tcl contribs examples doc/src
+SUB_DIRECTORIES = src tcl examples doc/src
include vsn.mk
VSN = $(GS_VSN)
diff --git a/lib/gs/contribs/Makefile b/lib/gs/contribs/Makefile
deleted file mode 100644
index 061fae86c1..0000000000
--- a/lib/gs/contribs/Makefile
+++ /dev/null
@@ -1,32 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1996-2009. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-
-#
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-SUB_DIRECTORIES = bonk cols mandel othello
-SPECIAL_TARGETS =
-
-#
-# Default Subdir Targets
-#
-include $(ERL_TOP)/make/otp_subdir.mk
-
diff --git a/lib/gs/contribs/bonk/Makefile b/lib/gs/contribs/bonk/Makefile
deleted file mode 100644
index b7508a97c9..0000000000
--- a/lib/gs/contribs/bonk/Makefile
+++ /dev/null
@@ -1,109 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1996-2012. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-
-#
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../../vsn.mk
-VSN=$(GS_VSN)
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/gs-$(VSN)/contribs
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-
-MODULES= \
- bonk \
- bonk_sound \
- bonk_square \
- sounder
-
-HRL_FILES=
-ERL_FILES= $(MODULES:%=%.erl)
-
-TARGET_FILES= $(MODULES:%=../ebin/%.$(EMULATOR)) $(TARGET_TOOLBOX_FILES)
-
-BITMAPS= bitmaps/bonkbomb bitmaps/bonkface bitmaps/bonklogo bitmaps/bonkmiss \
- bitmaps/bonktom bitmaps/bonkx bitmaps/erl-e bitmaps/erl-text
-SOUNDS= sounds/bonk.au sounds/damn.au sounds/explosion.au sounds/gameover.au \
- sounds/hehee.au sounds/level.au sounds/missedme.au sounds/music.au \
- sounds/ouch!!!.au sounds/praisejesus.au sounds/trumpet.au sounds/yes.au
-
-TOOLNAME = bonk
-
-EXTRA_FILES= $(TOOLNAME).txt
-TOOLBOX_FILES= $(TOOLNAME).tool $(TOOLNAME).gif
-TARGET_TOOLBOX_FILES= $(TOOLBOX_FILES:%=$(EBIN)/%)
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-ERL_COMPILE_FLAGS +=
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-
-debug opt: $(TARGET_FILES)
-
-docs:
-
-clean:
- rm -f $(TARGET_FILES)
- rm -f core
-
-# ----------------------------------------------------
-# Special Build Targets
-# ----------------------------------------------------
-
-$(EBIN)/$(TOOLNAME).gif: $(TOOLNAME).gif
- $(gen_verbose)rm -f $@
- $(V_at)cp $(TOOLNAME).gif $@
-
-$(EBIN)/$(TOOLNAME).tool: $(TOOLNAME).tool
- $(gen_verbose)rm -f $@
- $(V_at)cp $(TOOLNAME).tool $@
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-release_spec: opt
- $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
- $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
- $(INSTALL_DIR) "$(RELSYSDIR)/bonk/bitmaps"
- $(INSTALL_DATA) $(BITMAPS) $(TOOLBOX_FILES) "$(RELSYSDIR)/bonk/bitmaps"
- $(INSTALL_DIR) "$(RELSYSDIR)/bonk/sounds"
- $(INSTALL_DATA) $(SOUNDS) "$(RELSYSDIR)/bonk/sounds"
- $(INSTALL_DIR) "$(RELSYSDIR)/bonk"
- $(INSTALL_DATA) $(ERL_FILES) $(EXTRA_FILES) "$(RELSYSDIR)/bonk"
-
-
-release_docs_spec:
-
diff --git a/lib/gs/contribs/bonk/bitmaps/bonkbomb b/lib/gs/contribs/bonk/bitmaps/bonkbomb
deleted file mode 100644
index 8b121db9e8..0000000000
--- a/lib/gs/contribs/bonk/bitmaps/bonkbomb
+++ /dev/null
@@ -1,66 +0,0 @@
-#define bonkbomb_width 75
-#define bonkbomb_height 75
-static char bonkbomb_bits[] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x04, 0x10, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
- 0x10, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x21,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x11, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x90, 0x08, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x80, 0x90, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x04, 0x51, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
- 0x12, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x94, 0x18,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x41, 0x06, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xfc, 0xbb, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
- 0x99, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x18, 0x19,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x62, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x30, 0x84, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x80, 0x30, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xc0, 0x31, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0,
- 0x3b, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x1f, 0x40,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0xb8, 0x0e, 0x80, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xfc, 0x7f, 0x5c, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xff, 0xff, 0xaf, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff,
- 0xff, 0x57, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xaf,
- 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0x5f, 0x1d, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xbf, 0x0e, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xfc, 0xff, 0xff, 0x7f, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xfe, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff,
- 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfe, 0xff, 0xff,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfe, 0xff, 0xff, 0x01, 0x00,
- 0x00, 0x00, 0x00, 0x80, 0x7f, 0xfc, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00,
- 0x00, 0x80, 0x3f, 0xf8, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x80,
- 0x0f, 0xf0, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0xc0,
- 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x80, 0x7f, 0xf0, 0xff, 0xff,
- 0x03, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xf8, 0xff, 0xff, 0x07, 0x00,
- 0x00, 0x00, 0x00, 0xc0, 0xff, 0xfd, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00,
- 0x00, 0xc0, 0xff, 0xfd, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x80,
- 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff,
- 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff,
- 0x03, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00,
- 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff,
- 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x7f, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xf0, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xe0, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff,
- 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x01,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x7f, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/lib/gs/contribs/bonk/bitmaps/bonkface b/lib/gs/contribs/bonk/bitmaps/bonkface
deleted file mode 100644
index 964fb93098..0000000000
--- a/lib/gs/contribs/bonk/bitmaps/bonkface
+++ /dev/null
@@ -1,66 +0,0 @@
-#define bonkface_width 75
-#define bonkface_height 75
-static char bonkface_bits[] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x03,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x3c, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x80, 0x01, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
- 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
- 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x40, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08,
- 0x00, 0x80, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01, 0x30, 0x00, 0x60,
- 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x00, 0xc0, 0x00, 0x18, 0x00, 0x08,
- 0x00, 0x00, 0x00, 0x80, 0x07, 0x00, 0x03, 0x06, 0x00, 0x0f, 0x00, 0x00,
- 0x00, 0x40, 0xff, 0x00, 0x00, 0x00, 0xf8, 0x17, 0x00, 0x00, 0x00, 0x40,
- 0xfe, 0x1f, 0x00, 0xc0, 0xff, 0x13, 0x00, 0x00, 0x00, 0x20, 0xf8, 0xff,
- 0x03, 0xfe, 0xff, 0x20, 0x00, 0x00, 0x00, 0x20, 0xf0, 0xff, 0xff, 0xff,
- 0x7f, 0x20, 0x00, 0x00, 0x00, 0x20, 0xc0, 0xff, 0xdf, 0xff, 0x1f, 0x20,
- 0x00, 0x00, 0x00, 0x20, 0x00, 0xff, 0xdf, 0xff, 0x07, 0x20, 0x00, 0x00,
- 0x00, 0x10, 0x00, 0xfe, 0x8f, 0xff, 0x03, 0x40, 0x00, 0x00, 0x00, 0x10,
- 0x00, 0xf8, 0x8f, 0xff, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10, 0x00, 0xf0,
- 0x07, 0x7f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10, 0x00, 0xc0, 0x07, 0x1f,
- 0x00, 0x40, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x03, 0x06, 0x00, 0x40,
- 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
- 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10, 0x00, 0xe0,
- 0x00, 0x38, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10, 0x10, 0xf0, 0x01, 0x7c,
- 0x40, 0x40, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x06, 0x03, 0x40, 0x40,
- 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0xf8, 0x00, 0x40, 0x40, 0x00, 0x00,
- 0x00, 0x10, 0x30, 0x00, 0x00, 0x00, 0x60, 0x40, 0x00, 0x00, 0x00, 0x10,
- 0x70, 0x00, 0x00, 0x00, 0x70, 0x40, 0x00, 0x00, 0x00, 0x10, 0xf0, 0x01,
- 0x00, 0x00, 0x7c, 0x40, 0x00, 0x00, 0x00, 0x20, 0xf0, 0x0f, 0x00, 0x80,
- 0x7f, 0x20, 0x00, 0x00, 0x00, 0x20, 0xf0, 0xff, 0x03, 0xfe, 0x7f, 0x20,
- 0x00, 0x00, 0x00, 0x20, 0xf0, 0x7f, 0xfe, 0xff, 0x7f, 0x20, 0x00, 0x00,
- 0x00, 0x20, 0xe0, 0x7f, 0xfe, 0xff, 0x3f, 0x20, 0x00, 0x00, 0x00, 0x40,
- 0xe0, 0x7f, 0xfe, 0xff, 0x3f, 0x10, 0x00, 0x00, 0x00, 0x40, 0xc0, 0xff,
- 0xff, 0xff, 0x1f, 0x10, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xff, 0xff, 0xff,
- 0x1f, 0x08, 0x00, 0x00, 0x00, 0x80, 0x80, 0xff, 0xff, 0xff, 0x0f, 0x08,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0x07, 0x04, 0x00, 0x00,
- 0x00, 0x00, 0x01, 0xfe, 0xff, 0xff, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00,
- 0x02, 0xfc, 0xff, 0xfc, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x04, 0xf0,
- 0xff, 0x7c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0xc0, 0xff, 0x1c,
- 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0xff, 0x07, 0x40, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x80, 0x01, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,
- 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xc0,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x3c, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x03, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/lib/gs/contribs/bonk/bitmaps/bonklogo b/lib/gs/contribs/bonk/bitmaps/bonklogo
deleted file mode 100644
index 3adc59984a..0000000000
--- a/lib/gs/contribs/bonk/bitmaps/bonklogo
+++ /dev/null
@@ -1,320 +0,0 @@
-#define bonklogo_width 300
-#define bonklogo_height 100
-static char bonklogo_bits[] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0x3f, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00,
- 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
- 0x83, 0xff, 0x9f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x3c, 0xf8, 0xff, 0x7f, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x87, 0xff, 0xff, 0xff, 0x08, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x80, 0xf9, 0xff, 0xff, 0xff, 0x13, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0x27,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff,
- 0xff, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff,
- 0xff, 0xff, 0xff, 0x9f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x80, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x02, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0x0f,
- 0xfe, 0xff, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff,
- 0xff, 0x2f, 0xf8, 0xff, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x80, 0xdf, 0xff, 0x2f, 0xf0, 0xff, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x80, 0xc3, 0xff, 0x2f, 0xf0, 0xff, 0x09, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xff, 0x2f, 0xe0, 0xff, 0x0b, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x01, 0x00, 0x80, 0xff, 0x09,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0x2f, 0xc0, 0xff,
- 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xc0,
- 0xff, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0x27,
- 0xc0, 0xff, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x7f, 0x01,
- 0x00, 0xc0, 0xff, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
- 0xff, 0x17, 0xc0, 0xff, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
- 0x7f, 0x01, 0x00, 0xe0, 0xff, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xe0, 0xff, 0x17, 0xc0, 0xff, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xfc, 0x7f, 0x01, 0x00, 0xe0, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xe0, 0xff, 0x17, 0x80, 0xff, 0x17, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xfc, 0x7f, 0xff, 0x3f, 0xe0, 0x7f, 0x02, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x17, 0x80, 0xff, 0x17, 0xc0,
- 0xff, 0x7f, 0xe0, 0xff, 0x3f, 0xfc, 0x7f, 0x00, 0x20, 0xe0, 0x7f, 0x01,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x17, 0x80, 0xff,
- 0x17, 0x00, 0x00, 0x80, 0x00, 0x00, 0x20, 0xfc, 0x7f, 0xfe, 0x2f, 0xf0,
- 0x3f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x17,
- 0x80, 0xff, 0x17, 0xe0, 0xff, 0x1f, 0xe1, 0xff, 0x2f, 0xfc, 0x7f, 0xfe,
- 0x2f, 0xf0, 0x3f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0,
- 0xff, 0x17, 0x80, 0xff, 0x17, 0xf0, 0xff, 0x7f, 0xe6, 0xff, 0x4f, 0xfc,
- 0x7f, 0xfe, 0x2f, 0xf0, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xe0, 0xff, 0x17, 0x80, 0xff, 0x17, 0xf8, 0xff, 0xff, 0xe8, 0xff,
- 0x4f, 0xfc, 0x7f, 0xfe, 0x2f, 0xf8, 0x9f, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xe0, 0xff, 0x17, 0x80, 0xff, 0x17, 0xfe, 0xff, 0xff,
- 0xeb, 0xff, 0x5f, 0xfc, 0x7f, 0xfe, 0x2f, 0xf8, 0x9f, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x17, 0x80, 0xff, 0x17, 0xfe,
- 0xff, 0xff, 0xe3, 0xff, 0x5f, 0xfc, 0x7f, 0xfe, 0x2f, 0xf8, 0x5f, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x17, 0xc0, 0xff,
- 0x17, 0xff, 0xff, 0xff, 0xe7, 0xff, 0x5f, 0xfc, 0x7f, 0xfe, 0x2f, 0xfc,
- 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x17,
- 0xc0, 0xff, 0x93, 0xff, 0xff, 0xff, 0xe7, 0xff, 0x5f, 0xfc, 0x7f, 0xfe,
- 0x2f, 0xfc, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0,
- 0xff, 0x17, 0xc0, 0xff, 0x8b, 0xff, 0xff, 0xff, 0xe7, 0xff, 0x9f, 0xfc,
- 0x7f, 0xfe, 0x2f, 0xfc, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xe0, 0xff, 0x13, 0xe0, 0xff, 0x8b, 0xff, 0xff, 0xff, 0xcf, 0xff,
- 0xbf, 0xfc, 0x7f, 0xfe, 0x2f, 0xfc, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xf0, 0xff, 0x0b, 0xf2, 0xff, 0xcd, 0xff, 0xff, 0xff,
- 0xcf, 0xff, 0xbf, 0xfc, 0x7f, 0xfe, 0x2f, 0xfe, 0x17, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x0b, 0xf9, 0xff, 0xd9, 0xff,
- 0xff, 0xff, 0x1f, 0xff, 0xbf, 0xfc, 0x7f, 0xfe, 0x2f, 0xfe, 0x13, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xcb, 0xfc, 0xff,
- 0xc0, 0xff, 0x8f, 0xff, 0x1f, 0xff, 0xbf, 0xfc, 0x7f, 0xfe, 0x2f, 0xfe,
- 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x2b,
- 0xfe, 0xff, 0x87, 0xff, 0x03, 0xff, 0x3f, 0xff, 0xbf, 0xfc, 0x7f, 0xfe,
- 0x2f, 0xff, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
- 0xff, 0x9b, 0xff, 0xff, 0x3f, 0xff, 0x01, 0xfe, 0x3f, 0xff, 0x3f, 0xfd,
- 0x7f, 0xfe, 0x2f, 0xff, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xf0, 0xff, 0xc3, 0xff, 0xff, 0x7f, 0xfe, 0x05, 0xfc, 0x3f, 0xff,
- 0x7f, 0xfd, 0x7f, 0xfe, 0x2f, 0xff, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xf0, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xfc, 0x04, 0xfc,
- 0x3f, 0xff, 0x7f, 0xfd, 0x7f, 0xfe, 0x2f, 0xff, 0x04, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc,
- 0x02, 0xf8, 0x3f, 0xff, 0x7f, 0xfd, 0x7f, 0xfe, 0xaf, 0xff, 0x04, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xfd, 0x02, 0xf8, 0x3f, 0xff, 0x7f, 0xfc, 0x7f, 0xfe, 0xaf, 0xff,
- 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xf9, 0x02, 0xf8, 0x3f, 0xff, 0x7f, 0xfc, 0x7f, 0xfe,
- 0x8f, 0x7f, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0x02, 0xf8, 0x3f, 0xff, 0xff, 0xfc,
- 0x7f, 0xfe, 0xcf, 0x7f, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x02, 0xf8, 0x3f, 0xff,
- 0xff, 0xfc, 0x7f, 0xfe, 0xcf, 0x7f, 0x01, 0x00, 0x00, 0x38, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x02, 0xf8,
- 0x3f, 0xff, 0xff, 0xfc, 0x7f, 0xfe, 0xcf, 0x3f, 0x01, 0x00, 0x00, 0x38,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0xf7,
- 0x02, 0xf8, 0x3f, 0xff, 0xff, 0xfc, 0x7f, 0xfe, 0xef, 0x3f, 0x01, 0x00,
- 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x03, 0x80, 0xff,
- 0xff, 0xe7, 0x02, 0xf8, 0x3f, 0xff, 0xff, 0xfc, 0x7f, 0xfe, 0xef, 0x9f,
- 0x00, 0x00, 0x00, 0x00, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x01,
- 0x00, 0xff, 0xff, 0xe7, 0x02, 0xf8, 0x3f, 0xff, 0xff, 0xfd, 0x7f, 0xfe,
- 0xef, 0xdf, 0x00, 0x00, 0x00, 0x30, 0xd8, 0x07, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8,
- 0xff, 0x05, 0x00, 0xff, 0xff, 0xe7, 0x02, 0xf8, 0x3f, 0xff, 0xff, 0xfd,
- 0x7f, 0xfe, 0xef, 0x9f, 0x00, 0x00, 0x00, 0x38, 0xfc, 0x07, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xf8, 0xff, 0x05, 0x00, 0xff, 0xff, 0xef, 0x02, 0xf8, 0x3f, 0xff,
- 0xff, 0xfd, 0x7f, 0xfe, 0xff, 0xbf, 0x00, 0x00, 0x00, 0x38, 0x7c, 0x0e,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xf8, 0xff, 0x05, 0x00, 0xfe, 0xff, 0xef, 0x02, 0xf8,
- 0x3f, 0xff, 0xff, 0xfd, 0x7f, 0xfe, 0xff, 0x3f, 0x01, 0x00, 0x00, 0x38,
- 0x3e, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x05, 0x00, 0xfe, 0xff, 0xef,
- 0x02, 0xf8, 0x3f, 0xff, 0xff, 0xfd, 0x7f, 0xfe, 0xff, 0x7f, 0x02, 0x00,
- 0x00, 0x38, 0x3e, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x05, 0x00, 0xfc,
- 0xff, 0xcf, 0x02, 0xf8, 0x3f, 0xff, 0xff, 0xfd, 0x7f, 0xfe, 0xff, 0xff,
- 0x02, 0x00, 0x00, 0x38, 0x3b, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x04,
- 0x00, 0xfc, 0xff, 0xcf, 0x02, 0xf8, 0x3f, 0xff, 0xff, 0xff, 0x7f, 0xfe,
- 0xff, 0xff, 0x04, 0x00, 0x00, 0xb8, 0x39, 0x2e, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8,
- 0xff, 0x02, 0x00, 0xfc, 0xff, 0xcf, 0x02, 0xf8, 0x3f, 0xff, 0xff, 0xff,
- 0x7f, 0xfe, 0xff, 0xff, 0x05, 0x00, 0x00, 0xf0, 0x39, 0x3c, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xf8, 0xff, 0x02, 0x00, 0xfc, 0xff, 0xcf, 0x04, 0xf8, 0x3f, 0xff,
- 0xfd, 0xff, 0x7f, 0xfe, 0xff, 0xff, 0x09, 0x00, 0x00, 0xf0, 0x38, 0x1c,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xf8, 0xff, 0x02, 0x00, 0xfc, 0xff, 0xcf, 0x05, 0xf8,
- 0x3f, 0xff, 0xfd, 0xff, 0x7f, 0xfe, 0xff, 0xff, 0x13, 0x00, 0x00, 0x60,
- 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x02, 0x00, 0xfc, 0xff, 0xcf,
- 0x0d, 0xf8, 0x3f, 0xff, 0xfd, 0xff, 0x7f, 0xfe, 0xff, 0xff, 0x17, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x02, 0x00, 0xfe,
- 0xff, 0xcf, 0x09, 0xfd, 0x3f, 0xff, 0xfd, 0xff, 0x7f, 0xfe, 0xff, 0xff,
- 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x02,
- 0x00, 0xfe, 0xff, 0xcf, 0xcb, 0xfc, 0x3f, 0xff, 0xfd, 0xff, 0x7f, 0xfe,
- 0xff, 0xff, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
- 0xff, 0x02, 0x00, 0xfe, 0xff, 0xcf, 0x33, 0xfe, 0x3f, 0xff, 0xf9, 0xff,
- 0x7f, 0xfe, 0xff, 0xff, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xfc, 0xff, 0x02, 0x00, 0xfe, 0xff, 0xcf, 0x07, 0xff, 0x3f, 0xff,
- 0xf9, 0xff, 0x7f, 0xfe, 0xff, 0xff, 0x9f, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xfc, 0xff, 0x02, 0x00, 0xfe, 0xff, 0xcf, 0xcf, 0xff,
- 0x3f, 0xff, 0xf9, 0xff, 0x7f, 0xfe, 0x7f, 0xff, 0x3f, 0x01, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x02, 0x40, 0xfe, 0xff, 0xcf,
- 0xff, 0xff, 0x3f, 0xff, 0xf9, 0xff, 0x7f, 0xfe, 0x7f, 0xfe, 0x3f, 0x01,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x02, 0x3c, 0xff,
- 0xff, 0xc7, 0xff, 0xff, 0x3f, 0xff, 0xf9, 0xff, 0x7f, 0xfe, 0x7f, 0xfe,
- 0x7f, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x82,
- 0x87, 0xff, 0xff, 0xe7, 0xff, 0xff, 0x3f, 0xff, 0xf1, 0xff, 0x7f, 0xfe,
- 0x3f, 0xfc, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
- 0xff, 0x72, 0xf0, 0xff, 0xff, 0xe7, 0xff, 0xff, 0x3f, 0xff, 0xf1, 0xff,
- 0x7f, 0xfe, 0xbf, 0xf8, 0xff, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xfc, 0xff, 0x0e, 0xff, 0xff, 0xff, 0xe7, 0xff, 0xff, 0x9f, 0xff,
- 0xf5, 0xff, 0x7f, 0xfe, 0xbf, 0xf8, 0xff, 0x09, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xfc, 0xff, 0xe0, 0xff, 0xff, 0xff, 0xe7, 0xff, 0xff,
- 0x9f, 0xff, 0xf5, 0xff, 0x7f, 0xfe, 0x9f, 0xf0, 0xff, 0x0b, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7,
- 0xff, 0xff, 0x9f, 0xff, 0xf5, 0xff, 0x7f, 0xfe, 0x5f, 0xf0, 0xff, 0x13,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xfe, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xf3, 0xff, 0xff, 0xdf, 0xff, 0xf5, 0xff, 0x7f, 0xfe, 0x4f, 0xe0,
- 0xff, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xfe, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xf3, 0xff, 0xff, 0xcf, 0xff, 0xe5, 0xff, 0x7f, 0xfe,
- 0x2f, 0xe0, 0xff, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xff, 0xff, 0xcf, 0xff, 0xe5, 0xff,
- 0x7f, 0xfe, 0x2f, 0xc0, 0xff, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xff, 0xff, 0xe7, 0xff,
- 0xe5, 0xff, 0x7f, 0xfe, 0x2f, 0xc0, 0xff, 0x9f, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xf8, 0xff, 0xff,
- 0xe7, 0xff, 0xe5, 0xff, 0x7f, 0xfe, 0x2f, 0x80, 0xff, 0x9f, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfc,
- 0xff, 0xff, 0xf7, 0xff, 0xe5, 0xff, 0x7f, 0xfe, 0x2f, 0x00, 0xff, 0x3f,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0x1f, 0xfe, 0xff, 0xff, 0xf3, 0xff, 0xc5, 0xff, 0x7f, 0xfe, 0x2f, 0x00,
- 0xff, 0x7f, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0xf3, 0xff, 0xc5, 0xff, 0x7f, 0xfe,
- 0x2f, 0x00, 0xfe, 0x7f, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0x23, 0xff, 0xff, 0xff, 0xf1, 0xff, 0xc5, 0xff,
- 0x7f, 0xfe, 0x2f, 0x00, 0xfe, 0xff, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x11, 0xfe, 0xff, 0xff, 0xf5, 0xff,
- 0xc5, 0xff, 0x7f, 0xfe, 0x2f, 0x00, 0xfc, 0xff, 0x04, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x0c, 0xfc, 0xff, 0xff,
- 0xf4, 0xff, 0xc5, 0xff, 0x7f, 0xfe, 0x2f, 0x00, 0xfc, 0xff, 0x09, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x02, 0xfc,
- 0xff, 0x7f, 0xf2, 0xff, 0xc5, 0xff, 0x7f, 0xfe, 0x2f, 0x00, 0xf8, 0xff,
- 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x01,
- 0x00, 0xe0, 0xff, 0x3f, 0xf1, 0xff, 0x85, 0xff, 0x7f, 0xfe, 0x2f, 0x00,
- 0xf8, 0xff, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff,
- 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x85, 0xff, 0x7f, 0xfe,
- 0x2f, 0x00, 0xf0, 0xff, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff,
- 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x85, 0xff,
- 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xf0, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xf0, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x7f, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/lib/gs/contribs/bonk/bitmaps/bonkmiss b/lib/gs/contribs/bonk/bitmaps/bonkmiss
deleted file mode 100644
index 862e4839fc..0000000000
--- a/lib/gs/contribs/bonk/bitmaps/bonkmiss
+++ /dev/null
@@ -1,66 +0,0 @@
-#define bonkmiss_width 75
-#define bonkmiss_height 75
-static char bonkmiss_bits[] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x60, 0x80, 0x19, 0x3c, 0xc0, 0x83, 0xff, 0xf9, 0x01, 0x00, 0x60, 0x80,
- 0x19, 0x7e, 0xe0, 0x87, 0xff, 0xf9, 0x03, 0x00, 0xe0, 0xc0, 0x19, 0xe7,
- 0x70, 0x8e, 0x01, 0x18, 0x07, 0x00, 0xe0, 0xc0, 0x99, 0xc3, 0x39, 0x9c,
- 0x01, 0x18, 0x0e, 0x00, 0xe0, 0xe1, 0x99, 0x81, 0x19, 0x98, 0x01, 0x18,
- 0x0c, 0x00, 0xe0, 0xe1, 0x99, 0x81, 0x19, 0x98, 0x01, 0x18, 0x1c, 0x00,
- 0xe0, 0xf3, 0x99, 0x01, 0x18, 0x80, 0x01, 0x18, 0x18, 0x00, 0x60, 0xb3,
- 0x99, 0x01, 0x18, 0x80, 0x01, 0x18, 0x18, 0x00, 0x60, 0xb3, 0x99, 0x03,
- 0x38, 0x80, 0x01, 0x18, 0x18, 0x00, 0x60, 0x9e, 0x19, 0x07, 0x70, 0x80,
- 0x01, 0x18, 0x18, 0x00, 0x60, 0x9e, 0x19, 0x3e, 0xe0, 0x83, 0x1f, 0x18,
- 0x18, 0x00, 0x60, 0x8c, 0x19, 0x7c, 0xc0, 0x87, 0x1f, 0x18, 0x18, 0x00,
- 0x60, 0x80, 0x19, 0xe0, 0x00, 0x8e, 0x01, 0x18, 0x18, 0x00, 0x60, 0x80,
- 0x19, 0xc0, 0x01, 0x9c, 0x01, 0x18, 0x18, 0x00, 0x60, 0x80, 0x19, 0x80,
- 0x01, 0x98, 0x01, 0x18, 0x18, 0x00, 0x60, 0x80, 0x19, 0x80, 0x01, 0x98,
- 0x01, 0x18, 0x18, 0x00, 0x60, 0x80, 0x19, 0x80, 0x01, 0x98, 0x01, 0x18,
- 0x18, 0x00, 0x60, 0x80, 0x99, 0x81, 0x19, 0x98, 0x01, 0x18, 0x18, 0x00,
- 0x60, 0x80, 0x99, 0x81, 0x19, 0x98, 0x01, 0x18, 0x18, 0x00, 0x60, 0x80,
- 0x99, 0x81, 0x19, 0x98, 0x01, 0x18, 0x18, 0x00, 0x60, 0x80, 0x99, 0x81,
- 0x19, 0x98, 0x01, 0x18, 0x18, 0x00, 0x60, 0x80, 0x99, 0x81, 0x19, 0x98,
- 0x01, 0x18, 0x18, 0x00, 0x60, 0x80, 0x99, 0x81, 0x19, 0x98, 0x01, 0x18,
- 0x18, 0x00, 0x60, 0x80, 0x99, 0x81, 0x19, 0x98, 0x01, 0x18, 0x1c, 0x00,
- 0x60, 0x80, 0x99, 0x81, 0x19, 0x98, 0x01, 0x18, 0x0c, 0x00, 0x60, 0x80,
- 0x99, 0xc3, 0x39, 0x9c, 0x01, 0x18, 0x0e, 0x00, 0x60, 0x80, 0x19, 0xe7,
- 0x70, 0x8e, 0x01, 0x18, 0x07, 0x00, 0x60, 0x80, 0x19, 0x7e, 0xe0, 0x87,
- 0xff, 0xf9, 0x03, 0x00, 0x60, 0x80, 0x19, 0x3c, 0xc0, 0x83, 0xff, 0xf9,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0xff, 0x03, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0xff, 0x03, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x1c, 0x38, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x1c, 0x38, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
- 0x3c, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x3c, 0x03,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x3e, 0x03, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x36, 0x03, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x6c, 0x36, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xcc, 0x33, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc,
- 0x33, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8c, 0x31, 0x3f,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0x03, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0x03, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x0c, 0x30, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x0c, 0x30, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c,
- 0x30, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0x03,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0x03, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0x03, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x0c, 0x30, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x0c, 0x30, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c,
- 0x30, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0x03,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0x03, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0x03, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x0c, 0x30, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x0c, 0x30, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c,
- 0x30, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/lib/gs/contribs/bonk/bitmaps/bonktom b/lib/gs/contribs/bonk/bitmaps/bonktom
deleted file mode 100644
index defbc32cc9..0000000000
--- a/lib/gs/contribs/bonk/bitmaps/bonktom
+++ /dev/null
@@ -1,66 +0,0 @@
-#define bonktom_width 75
-#define bonktom_height 75
-static char bonktom_bits[] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/lib/gs/contribs/bonk/bitmaps/bonkx b/lib/gs/contribs/bonk/bitmaps/bonkx
deleted file mode 100644
index 70cd89bdb7..0000000000
--- a/lib/gs/contribs/bonk/bitmaps/bonkx
+++ /dev/null
@@ -1,66 +0,0 @@
-#define bonkx_width 75
-#define bonkx_height 75
-static char bonkx_bits[] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x03, 0x3e, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xf0, 0x03, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xf8, 0x03, 0xfc, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x01,
- 0xf8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0xf0, 0x07,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0xe0, 0x0f, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x80, 0x3f, 0x00, 0xc0, 0x1f, 0x00, 0x00, 0xfe, 0x03,
- 0x00, 0xc0, 0x1f, 0x00, 0x80, 0x3f, 0x00, 0xe0, 0x01, 0x3c, 0x00, 0xe0,
- 0x0f, 0x00, 0x00, 0x7f, 0x00, 0x18, 0x00, 0xc0, 0x00, 0xf0, 0x07, 0x00,
- 0x00, 0xfe, 0x00, 0x06, 0x00, 0x00, 0x03, 0xf8, 0x03, 0x00, 0x00, 0xfc,
- 0x81, 0x01, 0x00, 0x00, 0x0c, 0xfc, 0x01, 0x00, 0x00, 0xf8, 0x43, 0x00,
- 0x00, 0x00, 0x10, 0xfe, 0x00, 0x00, 0x00, 0xf0, 0x27, 0x00, 0x00, 0x00,
- 0x20, 0x7f, 0x00, 0x00, 0x00, 0xe0, 0x1f, 0x00, 0x00, 0x00, 0xc0, 0x3f,
- 0x00, 0x00, 0x00, 0xc0, 0x1f, 0x00, 0x00, 0x00, 0xc0, 0x1f, 0x00, 0x00,
- 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0x00, 0x00,
- 0x7f, 0x00, 0x00, 0x00, 0xf0, 0x07, 0x00, 0x00, 0x00, 0x00, 0xff, 0x08,
- 0x00, 0x80, 0xf8, 0x07, 0x00, 0x00, 0x00, 0x00, 0xfd, 0x31, 0x00, 0x60,
- 0xfc, 0x05, 0x00, 0x00, 0x00, 0x80, 0xf8, 0xc3, 0x00, 0x18, 0xfe, 0x08,
- 0x00, 0x00, 0x00, 0x80, 0xf7, 0x07, 0x03, 0x06, 0x7f, 0x0f, 0x00, 0x00,
- 0x00, 0x40, 0xff, 0x0f, 0x00, 0x80, 0xff, 0x17, 0x00, 0x00, 0x00, 0x40,
- 0xfe, 0x1f, 0x00, 0xc0, 0xff, 0x13, 0x00, 0x00, 0x00, 0x20, 0xf8, 0xff,
- 0x03, 0xfe, 0xff, 0x20, 0x00, 0x00, 0x00, 0x20, 0xf0, 0xff, 0xff, 0xff,
- 0x7f, 0x20, 0x00, 0x00, 0x00, 0x20, 0xc0, 0xff, 0xdf, 0xff, 0x1f, 0x20,
- 0x00, 0x00, 0x00, 0x20, 0x00, 0xff, 0xdf, 0xff, 0x07, 0x20, 0x00, 0x00,
- 0x00, 0x10, 0x00, 0xfe, 0x8f, 0xff, 0x03, 0x40, 0x00, 0x00, 0x00, 0x10,
- 0x00, 0xf8, 0x8f, 0xff, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10, 0x00, 0xf0,
- 0x8f, 0x7f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10, 0x00, 0xc0, 0xdf, 0x1f,
- 0x00, 0x40, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0xff, 0x0f, 0x00, 0x40,
- 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0xff, 0x07, 0x00, 0x40, 0x00, 0x00,
- 0x00, 0x10, 0x00, 0x00, 0xfe, 0x03, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10,
- 0x00, 0x00, 0xfc, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10, 0x00, 0xe0,
- 0xfe, 0x3b, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10, 0x10, 0xf0, 0xff, 0x7f,
- 0x40, 0x40, 0x00, 0x00, 0x00, 0x10, 0x10, 0x80, 0xff, 0x0f, 0x40, 0x40,
- 0x00, 0x00, 0x00, 0x10, 0x10, 0xc0, 0xff, 0x1f, 0x40, 0x40, 0x00, 0x00,
- 0x00, 0x10, 0x30, 0xe0, 0x8f, 0x3f, 0x60, 0x40, 0x00, 0x00, 0x00, 0x10,
- 0x70, 0xf0, 0x07, 0x7f, 0x70, 0x40, 0x00, 0x00, 0x00, 0x10, 0xf0, 0xf9,
- 0x03, 0xfe, 0x7c, 0x40, 0x00, 0x00, 0x00, 0x20, 0xf0, 0xff, 0x01, 0xfc,
- 0x7f, 0x20, 0x00, 0x00, 0x00, 0x20, 0xf0, 0xff, 0x03, 0xfe, 0x7f, 0x20,
- 0x00, 0x00, 0x00, 0x20, 0xf0, 0x7f, 0xfe, 0xff, 0x7f, 0x20, 0x00, 0x00,
- 0x00, 0x20, 0xe0, 0x7f, 0xfe, 0xff, 0x3f, 0x20, 0x00, 0x00, 0x00, 0x40,
- 0xe0, 0x7f, 0xfe, 0xff, 0x3f, 0x10, 0x00, 0x00, 0x00, 0x40, 0xe0, 0xff,
- 0xff, 0xff, 0x3f, 0x10, 0x00, 0x00, 0x00, 0x80, 0xf0, 0xff, 0xff, 0xff,
- 0x7f, 0x08, 0x00, 0x00, 0x00, 0x80, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x08,
- 0x00, 0x00, 0x00, 0x00, 0xfd, 0xff, 0xff, 0xff, 0xff, 0x05, 0x00, 0x00,
- 0x00, 0x00, 0xff, 0xfe, 0xff, 0xff, 0xfb, 0x07, 0x00, 0x00, 0x00, 0x00,
- 0x7f, 0xfc, 0xff, 0xfc, 0xf1, 0x07, 0x00, 0x00, 0x00, 0x80, 0x3f, 0xf0,
- 0xff, 0x7c, 0xe0, 0x0f, 0x00, 0x00, 0x00, 0xc0, 0x1f, 0xc0, 0xff, 0x1c,
- 0xc0, 0x1f, 0x00, 0x00, 0x00, 0xe0, 0x1f, 0x00, 0xff, 0x07, 0xc0, 0x3f,
- 0x00, 0x00, 0x00, 0xf0, 0x27, 0x00, 0x00, 0x00, 0x20, 0x7f, 0x00, 0x00,
- 0x00, 0xf8, 0x43, 0x00, 0x00, 0x00, 0x10, 0xfe, 0x00, 0x00, 0x00, 0xfc,
- 0x81, 0x01, 0x00, 0x00, 0x0c, 0xfc, 0x01, 0x00, 0x00, 0xfe, 0x00, 0x06,
- 0x00, 0x00, 0x03, 0xf8, 0x03, 0x00, 0x00, 0x7f, 0x00, 0x18, 0x00, 0xc0,
- 0x00, 0xf0, 0x07, 0x00, 0x80, 0x3f, 0x00, 0xe0, 0x01, 0x3c, 0x00, 0xe0,
- 0x0f, 0x00, 0xc0, 0x1f, 0x00, 0x00, 0xfe, 0x03, 0x00, 0xc0, 0x1f, 0x00,
- 0xe0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x00, 0xf0, 0x07,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0xf8, 0x03, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0xfc, 0x01, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xfc, 0x01, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xf8, 0x03, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x03,
- 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x1e, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/lib/gs/contribs/bonk/bitmaps/erl-e b/lib/gs/contribs/bonk/bitmaps/erl-e
deleted file mode 100644
index 41ad14f404..0000000000
--- a/lib/gs/contribs/bonk/bitmaps/erl-e
+++ /dev/null
@@ -1,106 +0,0 @@
-#define erl-e_width 108
-#define erl-e_height 88
-static char erl-e_bits[] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xf0, 0xfc, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xe0, 0xff, 0xf7, 0xfc, 0xff, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xf7, 0xfc, 0x7f, 0x00, 0x00,
- 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x80, 0xff, 0xf7, 0xfc, 0x3f,
- 0x00, 0x00, 0x00, 0x00, 0xfc, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf7,
- 0xfc, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00,
- 0xff, 0xf7, 0xfc, 0x1f, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0x00, 0x00,
- 0x00, 0x00, 0xfe, 0xf7, 0xfc, 0x1f, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff,
- 0x01, 0x00, 0x00, 0x00, 0xfe, 0xf7, 0xfc, 0x0f, 0x00, 0x00, 0x00, 0xe0,
- 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0xfc, 0xf7, 0xfc, 0x0f, 0x00, 0x00,
- 0x00, 0xf0, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0xfc, 0xf7, 0xfc, 0x07,
- 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0xf8, 0xf7,
- 0xfc, 0x07, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00,
- 0xf8, 0xf7, 0xfc, 0x03, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x0f, 0x00,
- 0x00, 0x00, 0xf8, 0xf7, 0xfc, 0x03, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff,
- 0x0f, 0x00, 0x00, 0x00, 0xf0, 0xf7, 0xfc, 0x01, 0x00, 0x00, 0x00, 0xfc,
- 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0xf0, 0xf7, 0xfc, 0x01, 0x00, 0x00,
- 0x00, 0xfc, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0xf0, 0xf7, 0xfc, 0x00,
- 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0xf0, 0xf7,
- 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xf0, 0xf7, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xe0, 0xf7, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xe0, 0xf7, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xf7, 0x7c, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xf7, 0x7c, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xf7,
- 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xe0, 0xf7, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xe0, 0xf7, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xe0, 0xf7, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xf7, 0x3c, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xf7, 0x3c, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xf7,
- 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xe0, 0xf7, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xc0, 0xf7, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xc0, 0xf7, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xf7, 0x3c, 0x00, 0x00, 0x00,
- 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0x3c, 0x00,
- 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7,
- 0x3c, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xf7, 0x3c, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xf7, 0x3c, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0x3c, 0x00, 0x00, 0x00, 0x00, 0xfe,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0x3c, 0x00, 0x00, 0x00,
- 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0x3c, 0x00,
- 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7,
- 0x3c, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xf7, 0x3c, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xf7, 0x3c, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0x3c, 0x00, 0x00, 0x00, 0x00, 0xfe,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0x7c, 0x00, 0x00, 0x00,
- 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0x7c, 0x00,
- 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7,
- 0x7c, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xf7, 0x7c, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff,
- 0x7f, 0xfe, 0xff, 0xf7, 0xfc, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff,
- 0xff, 0xff, 0x3f, 0xf8, 0xff, 0xf7, 0xfc, 0x00, 0x00, 0x00, 0x00, 0xf8,
- 0xff, 0xff, 0xff, 0xff, 0x3f, 0xe0, 0xff, 0xf7, 0xfc, 0x00, 0x00, 0x00,
- 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xc0, 0xff, 0xf7, 0xfc, 0x01,
- 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0xfe, 0xf7,
- 0xfc, 0x01, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00,
- 0xf8, 0xf7, 0xfc, 0x01, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff,
- 0x03, 0x00, 0xe0, 0xf7, 0xfc, 0x03, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff,
- 0xff, 0xff, 0x03, 0x00, 0xc0, 0xf7, 0xfc, 0x03, 0x00, 0x00, 0x00, 0xc0,
- 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x80, 0xf7, 0xfc, 0x07, 0x00, 0x00,
- 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x80, 0xf7, 0xfc, 0x07,
- 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x80, 0xf7,
- 0xfc, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0x1f, 0x00, 0x00,
- 0xc0, 0xf7, 0xfc, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x0f,
- 0x00, 0x00, 0xe0, 0xf7, 0xfc, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff,
- 0xff, 0x07, 0x00, 0x00, 0xe0, 0xf7, 0xfc, 0x1f, 0x00, 0x00, 0x00, 0x00,
- 0xf0, 0xff, 0xff, 0x03, 0x00, 0x00, 0xf0, 0xf7, 0xfc, 0x3f, 0x00, 0x00,
- 0x00, 0x00, 0x80, 0xff, 0x7f, 0x00, 0x00, 0x00, 0xf8, 0xf7, 0xfc, 0x7f,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00, 0x00, 0xfc, 0xf7,
- 0xfc, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xfc, 0xf7, 0xfc, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xfe, 0xf7, 0xfc, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xff, 0xf7, 0xfc, 0xff, 0x03, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xf7, 0xfc, 0xff, 0x07, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xf7, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0};
diff --git a/lib/gs/contribs/bonk/bitmaps/erl-text b/lib/gs/contribs/bonk/bitmaps/erl-text
deleted file mode 100644
index e20a9e5a28..0000000000
--- a/lib/gs/contribs/bonk/bitmaps/erl-text
+++ /dev/null
@@ -1,106 +0,0 @@
-#define erl-text_width 108
-#define erl-text_height 88
-static char erl-text_bits[] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
- 0xfc, 0x03, 0xf8, 0x00, 0x70, 0x00, 0x80, 0x03, 0x80, 0x03, 0x07, 0x00,
- 0x3e, 0xf0, 0xfc, 0x03, 0xf8, 0x03, 0x70, 0x00, 0x80, 0x03, 0x80, 0x07,
- 0x07, 0x80, 0xff, 0xf0, 0xfc, 0x03, 0xf8, 0x07, 0x70, 0x00, 0xc0, 0x07,
- 0x80, 0x07, 0x07, 0xe0, 0xff, 0xf1, 0x1c, 0x00, 0x38, 0x07, 0x70, 0x00,
- 0xc0, 0x07, 0x80, 0x0f, 0x07, 0xe0, 0xc1, 0xf3, 0x1c, 0x00, 0x38, 0x0e,
- 0x70, 0x00, 0xe0, 0x0f, 0x80, 0x1f, 0x07, 0xf0, 0x80, 0xf3, 0x1c, 0x00,
- 0x38, 0x0f, 0x70, 0x00, 0xe0, 0x0e, 0x80, 0x1f, 0x07, 0x78, 0x00, 0xf0,
- 0xfc, 0x03, 0xf8, 0x07, 0x70, 0x00, 0xe0, 0x0e, 0x80, 0x3f, 0x07, 0x78,
- 0x00, 0xf0, 0xfc, 0x03, 0xf8, 0x03, 0x70, 0x00, 0x70, 0x1c, 0x80, 0x7b,
- 0x07, 0x38, 0x00, 0xf0, 0xfc, 0x03, 0xf8, 0x01, 0x70, 0x00, 0x70, 0x1c,
- 0x80, 0xf3, 0x07, 0x38, 0xf8, 0xf7, 0x1c, 0x00, 0xf8, 0x01, 0x70, 0x00,
- 0x70, 0x1c, 0x80, 0xe3, 0x07, 0x78, 0xf8, 0xf7, 0x1c, 0x00, 0xf8, 0x03,
- 0x70, 0x00, 0xf8, 0x3f, 0x80, 0xe3, 0x07, 0x70, 0x80, 0xf7, 0x1c, 0x00,
- 0xb8, 0x03, 0x70, 0x00, 0xf8, 0x3f, 0x80, 0xc3, 0x07, 0xf0, 0x80, 0xf3,
- 0xfc, 0x03, 0x38, 0x07, 0xf0, 0x07, 0x38, 0x38, 0x80, 0x83, 0x07, 0xe0,
- 0xe3, 0xf3, 0xfc, 0x03, 0x38, 0x07, 0xf0, 0x07, 0x1c, 0x70, 0x80, 0x83,
- 0x07, 0xc0, 0xff, 0xf1, 0xfc, 0x03, 0x38, 0x0e, 0xf0, 0x07, 0x1c, 0x70,
- 0x80, 0x03, 0x07, 0x00, 0x7f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0};
diff --git a/lib/gs/contribs/bonk/bonk.erl b/lib/gs/contribs/bonk/bonk.erl
deleted file mode 100644
index bbbc656b34..0000000000
--- a/lib/gs/contribs/bonk/bonk.erl
+++ /dev/null
@@ -1,584 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%
--module(bonk).
--compile([{nowarn_deprecated_function,{gs,config,2}},
- {nowarn_deprecated_function,{gs,create,3}},
- {nowarn_deprecated_function,{gs,create,4}},
- {nowarn_deprecated_function,{gs,destroy,1}},
- {nowarn_deprecated_function,{gs,start,0}}]).
-
--export([run/0, run/1,bonk_dir/0,start/0]).
-
--record(colors, {miss, x, bomb, face}).
--record(scores, {points, level, bombs, hits, showed, bonus}).
-
-start() ->
- spawn(bonk, run, []).
-
-run() ->
- run(color).
-
-run([ColorMode]) -> % This is for the start script...
- run(ColorMode);
-
-run(ColorMode) when is_atom(ColorMode) ->
- GS = gs:start(),
- SoundPid = spawn_link(bonk_sound,start,[]),
- {H,M,S} = time(),
- random:seed(H*13,M*7,S*3),
- {SqrPids, Bmps, Colors} = create_board(GS, ColorMode),
- {ScoreL,_File} = get_highscore(),
- display_highscore(ScoreL),
- put(colormode, ColorMode),
- SoundPid ! music,
- sleep(6500),
- gs:config(aboutButton, [{enable,true}]),
- gs:config(newButton, [{enable,true}]),
- gs:config(quitButton, [{enable,true}]),
- idle(SoundPid, SqrPids, Bmps, Colors).
-
-%% This is not an application so we don't have their way of knowing
-%% a private data directory where the GIF files are located (this directory).
-%% We can find GS and makes it relative from there /kgb
-%%
-%% Note the silly slash that is added. The rest of the code uses
-%% append to contruct file names and assumes that the directory ends
-%% in slash. If filename:join was used and the problem is gone.
-
--define(EbinFromGsPriv,"../contribs/bonk").
-
-bonk_dir() ->
- GsPrivDir = code:priv_dir(gs),
- filename:join(GsPrivDir,?EbinFromGsPriv) ++ "/".
-
-
-idle(SoundPid, SqrPids, Bmps, Colors) ->
- receive
- {gs, newButton, click, _Data, _Args} ->
- init(SoundPid, SqrPids, Bmps, Colors);
- {gs, aboutButton, click, _Data, _Args} ->
- display_about(),
- idle(SoundPid, SqrPids, Bmps, Colors);
- {gs, quitButton, click, _Data, _Args} ->
- SoundPid ! quit,
- send_to_all(SqrPids, quit);
- _Other ->
- %%io:format("Got ~w in idle~n", [_Other]),
- idle(SoundPid, SqrPids, Bmps, Colors)
- end.
-
-
-
-init(SoundPid, SqrPids, Bmps, Colors) ->
- clear_board(Bmps),
- SoundPid ! start,
- gs:config(newButton, [{enable,false}]),
- gs:config(endButton, [{enable,true}]),
- gs:config(aboutButton, [{enable,false}]),
- Scores = #scores{points=0, level=1, bombs=0, hits=0, showed=0, bonus=10},
- clear_scores(Scores),
- flush(),
- send_to_all(SqrPids, start),
- game(SoundPid, SqrPids, Bmps, Colors, Scores).
-
-
-game(SoundPid, SqrPids, Bmps, Colors, Scores) ->
- receive
- {gs, _Square, buttonpress, SqrPid, [1 | _Rest]} when is_pid(SqrPid) ->
- SqrPid ! bonk,
- game(SoundPid, SqrPids, Bmps, Colors, Scores);
- {gs, _Id, buttonpress, _Data, [Butt | _Rest]} when Butt =/= 1 ->
- NewScores = bomb(SoundPid, SqrPids, Scores),
- game(SoundPid, SqrPids, Bmps, Colors, NewScores);
- {show, Square, Rect} ->
- NewScores = show_face(Square, Rect, Colors, Scores),
- game(SoundPid, SqrPids, Bmps, Colors, NewScores);
- {hide, Square, Rect} ->
- NewScores = hide_face(Square, Rect, Colors, Scores),
- game(SoundPid, SqrPids, Bmps, Colors, NewScores);
- {missed, Square, Rect} ->
- case miss_face(SoundPid, Square, Rect, Colors, Scores) of
- {continue, NewScores} ->
- game(SoundPid, SqrPids, Bmps, Colors, NewScores);
- {game_over, NewScores} ->
- game_over(SoundPid, SqrPids, Bmps, Colors, NewScores)
- end;
- {bonked, Square, Rect} ->
- NewScores = bonked(SoundPid, SqrPids, Square, Rect, Scores, Colors),
- game(SoundPid, SqrPids, Bmps, Colors, NewScores);
- {bombed, Square, Rect} ->
- NewScores = bombed(SoundPid, SqrPids, Square, Rect, Scores, Colors),
- game(SoundPid, SqrPids, Bmps, Colors, NewScores);
- {gs, endButton, click, _Data, _Args} ->
- game_over(SoundPid, SqrPids, Bmps, Colors, Scores);
- {gs, quitButton, click, _Data, _Args} ->
- quit(SoundPid, SqrPids, Bmps, Colors, Scores);
- _Other ->
- game(SoundPid, SqrPids, Bmps, Colors, Scores)
- end.
-
-
-
-game_over(SoundPid, SqrPids, Bmps, Colors, Scores) ->
- SoundPid ! game_over,
- send_to_all(SqrPids, stop),
- flush(),
- sleep(2000),
- update_scorelist(SoundPid, Scores),
- gs:config(newButton, [{enable,true}]),
- gs:config(endButton, [{enable,false}]),
- gs:config(aboutButton, [{enable,true}]),
- idle(SoundPid, SqrPids, Bmps, Colors).
-
-
-quit(SoundPid, SqrPids, _Bmps, _Colors, _Scores) ->
- SoundPid ! quit,
- send_to_all(SqrPids, quit),
- true.
-
-
-
-bomb(SoundPid, SqrPids, Scores) ->
- case Scores#scores.bombs of
- Bombs when Bombs > 0 ->
- send_to_all(SqrPids, bomb),
- SoundPid ! bomb,
- gs:config(bombOut,[{text,integer_to_list(Bombs-1)}]),
- Scores#scores{bombs=Bombs-1};
- _Other ->
- Scores
- end.
-
-show_face(Square, Rect, Colors, Scores) ->
- Showed = Scores#scores.showed,
- if
- Showed == Scores#scores.level+1 ->
- Square ! sleep,
- Scores;
- true ->
- FaceColors = Colors#colors.face,
- FaceColor = lists:nth(random:uniform(length(FaceColors)), FaceColors),
- gs:config(Rect, [{bitmap,lists:append(bonk_dir(),"bitmaps/bonkface")},{fg, FaceColor}]),
- Scores#scores{showed=Showed+1}
- end.
-
-hide_face(_Square, Rect, _Colors, Scores) ->
- Showed = Scores#scores.showed,
- gs:config(Rect, [{bitmap,lists:append(bonk_dir(),"bitmaps/bonktom")}]),
- Scores#scores{showed=Showed-1}.
-
-
-miss_face(SoundPid, _Square, Rect, Colors, Scores) ->
- SoundPid ! missed,
- gs:config(Rect, [{bitmap,lists:append(bonk_dir(),"bitmaps/bonkmiss")}, {fg, Colors#colors.miss}]),
- Bonus = Scores#scores.bonus,
- if
- Bonus > 1 ->
- gs:config(bonusOut, [{text,integer_to_list(Bonus-1)}]),
- {continue, Scores#scores{bonus=Bonus-1}};
- true ->
- gs:config(bonusOut, [{text,"0"}]),
- {game_over, Scores}
- end.
-
-bonked(SoundPid, SqrPids, _Square, Rect, Scores, Colors) ->
- gs:config(Rect, [{bitmap,lists:append(bonk_dir(),"bitmaps/bonkx")}, {fg, Colors#colors.x}]),
- SoundPid ! bonk,
- update_score(SoundPid, SqrPids, Scores).
-
-bombed(SoundPid, SqrPids, _Square, Rect, Scores, Colors) ->
- gs:config(Rect, [{bitmap,lists:append(bonk_dir(),"bitmaps/bonkbomb")}, {fg, Colors#colors.bomb}]),
- update_score(SoundPid, SqrPids, Scores).
-
-
-update_score(SoundPid, SqrPids, Scores) ->
- Points = Scores#scores.points,
- Level = Scores#scores.level,
- NewPoints = Points+Level,
- gs:config(scoreOut,[{text,integer_to_list(NewPoints)}]),
- case Scores#scores.hits of
- 24 ->
- SoundPid ! new_level,
- NewLevel = Level+1,
- NewBombs = Scores#scores.bombs+1,
- send_to_all(SqrPids, {new_level, NewLevel}),
- gs:config(levelOut,[{text,integer_to_list(NewLevel)}]),
- gs:config(bombOut,[{text,integer_to_list(NewBombs)}]),
- Scores#scores{points=NewPoints, level=NewLevel, hits=0, bombs=NewBombs};
- Hits ->
- Scores#scores{points=NewPoints, hits=Hits+1}
- end.
-
-
-send_to_all([], _Msg) ->
- true;
-send_to_all([Pid|Rest],Msg) when is_pid(Pid) ->
- Pid ! Msg,
- send_to_all(Rest,Msg);
-send_to_all([_Else|Rest],Msg) ->
- send_to_all(Rest,Msg).
-
-
-create_board(GS, ColorMode) ->
- Colors =
- case ColorMode of
- bw -> #colors{miss=white, x=white, bomb=white, face=[white]};
- _Color -> #colors{miss=red, x=green, bomb=white,
- face=[lightblue, orange, magenta, peachpuff, pink]}
- end,
- BGCol = if ColorMode==bw -> black; true -> black end, % background color
- TextCol = if ColorMode==bw -> white; true -> pink end, % status texts
- NrCol = if ColorMode==bw -> white; true -> purple end, % status figures
- LogoCol = if ColorMode==bw -> white; true -> green end, % bonk logo
- BLineCol = if ColorMode==bw -> white; true -> grey end, % button line
- SLineCol = if ColorMode==bw -> white; true -> red end, % status line
- BTextCol = if ColorMode==bw -> white; true -> orange end, % button text
- HiHeadCol = if ColorMode==bw -> white; true -> red end, % high score label
- HiCol = if ColorMode==bw -> white; true -> cyan end, % high scores
- SquareCol = if ColorMode==bw -> white; true -> yellow end, % game squares
- ErlFgCol = if ColorMode==bw -> white; true -> red end, %
- ErlBGCol = if ColorMode==bw -> black; true -> white end, %
- ErlTxtCol = if ColorMode==bw -> white; true -> black end, %
-
- Width = 550, % width of bonk window
- Height = 550, % Height of bonk window
-
- BX = 0, % x-pos for first button
- DBX = 100, % space between buttons
- BY = 0, % y-pos for buttons
- BLineY = 30, % y-pos of button line
- LogoX = (Width-320) div 2, % x-pos of bonk logo (logo is 320 pix wide)
- LogoY = BLineY+2, % y-pos of bonk logo
- ErlLogoX = LogoX + 200, % x-pos of Erlang e
- ErlLogoY = LogoY + 10, % y-pos of Erlang e
- SLineY = Height-22, % status line position
- TextWidth = 50, % text width of status items
- SX = 2, % x-pos for first status item
- DSX = TextWidth+94, % pixels between status items
- SY = SLineY+2, % y-pos status items
- HiWidth = 100, % width of high score field
- _HiHeight = 180, % height of the same
- HiX = Width-HiWidth, % high score text position
- HiY = BLineY+10,
- DHY = 20, % space between title & scores
- SquareSize = 76, % size of each game square
- SquareSpace = 1, % space between game squares
- SquareX = 40,
- SquareY = 65,
-
- gs:create(window, bonkWin, GS, [{width, Width}, {height, Height},
- {bg, BGCol},
- {title, "Bonk the game"},
- {iconname, "Bonk!"},
- {map, false}]),
- gs:create(canvas, bonkCanvas, bonkWin, [{width, Width},
- {height, Height},
- {bg, BGCol}]),
- gs:create(image, bonkCanvas, [{bitmap,lists:append(bonk_dir(), "bitmaps/bonklogo")},
- {coords, [{LogoX, LogoY}]},
- {fg, LogoCol},
- {bg, BGCol}]),
- gs:create(image, bonkCanvas, [{bitmap,lists:append(bonk_dir(), "bitmaps/erl-e")},
- {coords, [{ErlLogoX, ErlLogoY}]},
- {fg, ErlFgCol},
- {bg, ErlBGCol}]),
- gs:create(image, bonkCanvas, [{bitmap,lists:append(bonk_dir(), "bitmaps/erl-text")},
- {coords, [{ErlLogoX, ErlLogoY}]},
- {fg, ErlTxtCol}]),
- gs:create(line, bLine, bonkCanvas, [{coords, [{0,BLineY}, {Width,BLineY}]},
- {fg, BLineCol},
- {width, 2}]),
- gs:create(line, bLine, bonkCanvas, [{coords, [{0,SLineY}, {Width, SLineY}]},
- {fg, SLineCol},
- {width, 2}]),
- gs:create(text, scoreText, bonkCanvas, [{coords, [{SX, SY}]},
- {fg, TextCol},
- {text, "Score:"}]),
- gs:create(text, scoreOut, bonkCanvas, [{coords, [{SX+TextWidth, SY}]},
- {fg, NrCol},
- {width, DSX-TextWidth},
- {text, ""}]),
- gs:create(text, bombText, bonkCanvas, [{coords, [{SX+DSX, SY}]},
- {fg, TextCol},
- {text, "Bombs:"}]),
- gs:create(text, bombOut, bonkCanvas, [{coords, [{SX+DSX+TextWidth, SY}]},
- {fg, NrCol},
- {width, DSX-TextWidth},
- {text, ""}]),
- gs:create(text, bonusText, bonkCanvas, [{coords, [{SX+2*DSX, SY}]},
- {fg, TextCol},
- {text, "Bonus:"}]),
- gs:create(text, bonusOut, bonkCanvas, [{coords, [{SX+2*DSX+TextWidth, SY}]},
- {fg, NrCol},
- {width, DSX-TextWidth},
- {text, ""}]),
- gs:create(text, levelText,bonkCanvas, [{coords, [{SX+3*DSX, SY}]},
- {fg, TextCol},
- {text, "Level:"}]),
- gs:create(text, levelOut, bonkCanvas, [{coords, [{SX+3*DSX+TextWidth, SY}]},
- {fg, NrCol},
- {width, DSX-TextWidth},
- {text, ""}]),
- gs:create(text, hiScoreText, bonkCanvas, [{coords, [{HiX, HiY}]},
- {fg, HiHeadCol},
- {text, "High Scores"}]),
- gs:create(text, hiScoreOut, bonkCanvas, [{coords, [{HiX, HiY+DHY}]},
- {fg, HiCol},
- {justify, left},
- {width, HiWidth}]),
- gs:create(button, newButton,bonkWin, [{x, BX},{y, BY},
- {enable,false},
- {label, {text, "New Game"}},
- {click, true},
- {fg, BTextCol},
- {bg, BGCol},
- {relief, flat},
- {activefg, BTextCol},
- {activebg, BGCol},
- {align, center}]),
- gs:create(button, endButton,bonkWin, [{x, BX+DBX},{y, BY},
- {enable,false},
- {label, {text, "End Game"}},
- {click, true},
- {fg, BTextCol},
- {bg, BGCol},
- {relief, flat},
- {activefg, BTextCol},
- {activebg, BGCol},
- {align, center}]),
- gs:create(button, aboutButton,bonkWin, [{x, BX+2*DBX},{y, BY},
- {enable,false},
- {label, {text, "About"}},
- {click, true},
- {fg, BTextCol},
- {bg, BGCol},
- {relief, flat},
- {activefg, BTextCol},
- {activebg, BGCol},
- {align, center}]),
- gs:create(button, quitButton, bonkWin, [{x, BX+3*DBX},{y, BY},
- {enable,false},
- {label, {text, "Quit"}},
- {click, true},
- {fg, BTextCol},
- {bg, BGCol},
- {relief, flat},
- {activefg, BTextCol},
- {activebg, BGCol},
- {align, center}]),
-
- {SqrPids, Bmps} =
- create_squares(SquareX, SquareY, SquareSize, SquareCol, SquareSpace),
- gs:config(bonkWin, [{map, true}]),
- {SqrPids, Bmps, Colors}.
-
-
-
-create_squares(X, Y, Size, Color, Spc) ->
- create_squares(X, Y, Size, Color, Spc, 1, 1, [], []).
-
-
-create_squares(_X, _Y, _Size, _Color, _Spc, 4, 5, Pids, Bmps) ->
- {Pids, Bmps};
-
-create_squares(X, Y, Size, Color, Spc, Row, 5, Pids, Bmps) ->
- create_squares(X, Y, Size, Color, Spc, Row+1, 1, Pids, Bmps);
-
-create_squares(X, Y, Size, Color, Spc, Row, Col, Pids, Bmps) ->
- Xpos = X+Col*Size+(Col-1)*Spc,
- Ypos = Y+Row*Size+(Row-1)*Spc,
- gs:create(rectangle, bonkCanvas,
- [{coords, [{Xpos,Ypos},{Xpos+Size, Ypos+Size}]},
- {bw, 2},{fg, Color},{buttonpress,true}]),
- Bmp = gs:create(image, bonkCanvas,
- [{coords, [{Xpos+1, Ypos+1}]},
- {bitmap,lists:append(bonk_dir(), "bitmaps/bonktom")},
- {buttonpress, true},{fg, Color}]),
- Pid = bonk_square:start(Bmp),
- gs:config(Bmp, [{data, Pid}]),
- create_squares(X, Y, Size, Color, Spc, Row, Col+1, [Pid|Pids], [Bmp|Bmps]).
-
-
-
-clear_board([]) ->
- true;
-clear_board([Square | Rest]) ->
- gs:config(Square, [{bitmap,lists:append(bonk_dir(), "bitmaps/bonktom")}]),
- clear_board(Rest).
-
-
-%% Prints the list on the screen.
-%% The list is on the form [[Score,Name],[Score,Name]..].
-
-display_highscore(ScoreList) ->
- display_highscore("",ScoreList,0).
-
-display_highscore(Scores,[],_N) ->
- gs:config(hiScoreOut,[{text,Scores}]);
-
-display_highscore(Scores,_ScoreList,10) -> % This is max number of items.
- display_highscore(Scores,[], 10);
-
-display_highscore(Scores,[[Score,Name]|Rest],N) ->
- NewScores = lists:append(Scores,lists:append(lists:append(Score, [32 | Name]), [10])),
- display_highscore(NewScores,Rest,N+1).
-
-
-%% Reads the highscorelist from the file "bonk.score".
-%% The list should be an sorted erlang-list.
-
-get_highscore() ->
- case file:consult("bonk.score") of
- {ok,[Score_list]} ->
- {Score_list,"./bonk.score"};
- {error,_} ->
- {[],"./bonk.score"}
- end.
-
-
-%% Prints out the highscorelist and places the new score in the
-%% list if it is high enough.
-
-update_scorelist(SoundPid, Scores) ->
- case Scores#scores.points of
- 0 -> true;
- Score ->
- {ScoreL,FileName} = get_highscore(),
- New_scorelist=update_scorelist_2(ScoreL, Score, 0, SoundPid),
- display_highscore(New_scorelist),
- case file:open(FileName, [write]) of
- {error,_} ->
- true;
- {ok,FD} ->
- io:format(FD,"~w~s~n",[New_scorelist,"."]),
- file:close(FD)
- end
- end.
-
-
-update_scorelist_2([], Score, N, _SoundPid) when N < 10 ->
- [[integer_to_list(Score),getuser()]];
-
-update_scorelist_2(_, _, N, _SoundPid) when N >= 10 ->
- [];
-
-update_scorelist_2([[Sc, Name] | Rest], Score, N, SoundPid) ->
- case list_to_integer(Sc) of
- Sc_int when Sc_int < Score ->
- if
- N == 0 -> SoundPid ! best_score;
- true -> SoundPid ! high_score
- end,
- lists:append([[integer_to_list(Score),getuser()]],
- update_scorelist_3([[Sc,Name]|Rest],N+1));
- _Other ->
- lists:append([[Sc,Name]],update_scorelist_2(Rest, Score, N+1, SoundPid))
- end.
-
-
-update_scorelist_3([],_) ->
- [];
-
-update_scorelist_3(_,N) when N >= 10 ->
- [];
-
-update_scorelist_3([Item|Rest],N) ->
- lists:append([Item],update_scorelist_3(Rest,N+1)).
-
-getuser() ->
- case os:type() of
- {unix,_} ->
- lists:delete(10,os:cmd("whoami"));
- _ ->
- "Unknown"
- end.
-
-%% Prints out the initial values of scores, bonus, level and bombs.
-
-clear_scores(Scores) ->
- Score = integer_to_list(Scores#scores.points),
- Bombs = integer_to_list(Scores#scores.bombs),
- Bonus = integer_to_list(Scores#scores.bonus),
- Level = integer_to_list(Scores#scores.level),
- gs:config(scoreOut,{text,Score}),
- gs:config(bombOut,{text,Bombs}),
- gs:config(bonusOut,{text,Bonus}),
- gs:config(levelOut,{text,Level}).
-
-
-%% Removes everything that is present in the message-que.
-
-flush() ->
- receive
- _X ->
- flush()
- after
- 0 ->
- true
- end.
-
-sleep(X) ->
- receive after X -> true end.
-
-%% Opens a window and shows the contents of the file: "bonk.txt".
-%% The window will be removed before the function ends.
-
-display_about() ->
- {BGColor,TextColor,Bfg} =
- case get(colormode) of
- bw -> {black, white, white};
- _Color -> {black, peachpuff1, orange}
- end,
- Wid = 500, Hei = 635,
- GS = gs:start(),
- gs:create(window, aboutWin, GS, [{width, Wid}, {height,Hei},
- {map, false},
- {bg, BGColor},
- {title, "About Bonk!"}]),
- gs:create(canvas, aboutCan, aboutWin, [{width, Wid},{height, Hei},
- {bg, black}]),
- gs:create(button, okButton, aboutWin, [{x, Wid div 2 - 50},{y, Hei - 40},
- {label,{text, "Ok"}}, {click, true},
- {fg, Bfg}, {bg, BGColor},
- {relief, flat},
- {activefg, Bfg},
- {activebg, BGColor}]),
- gs:create(text, aboutText, aboutCan, [{width, Wid-30}, {coords, [{15, 0}]},
- {fg, TextColor}, {justify, center}]),
- case file:open(lists:append(bonk_dir(),"bonk.txt"), [read]) of
- {ok, Fd} ->
- write_text(Fd, "", io:get_line(Fd, "")),
- file:close(Fd);
- {error, _Reason} ->
- gs:config(aboutText, {text, "Error: could not read the about file"})
- end,
-
- gs:config(aboutWin, [{map,true}]),
- receive
- {gs, okButton, click, _, _} ->
- gs:destroy(aboutWin)
- end.
-
-write_text(_Fd, Text, eof) ->
- gs:config(aboutText, {text, Text});
-write_text(Fd, Text, More) ->
- write_text(Fd, lists:append(Text, More), io:get_line(Fd, "")).
diff --git a/lib/gs/contribs/bonk/bonk.gif b/lib/gs/contribs/bonk/bonk.gif
deleted file mode 100644
index 3c2299686b..0000000000
--- a/lib/gs/contribs/bonk/bonk.gif
+++ /dev/null
Binary files differ
diff --git a/lib/gs/contribs/bonk/bonk.tool b/lib/gs/contribs/bonk/bonk.tool
deleted file mode 100644
index 79ad8f6701..0000000000
--- a/lib/gs/contribs/bonk/bonk.tool
+++ /dev/null
@@ -1,6 +0,0 @@
-{version,"0.1"}.
-{{tool,"Bonk"},
- {start,{bonk,start,[]}},
- {icon,"bonk.gif"},
- {message,"Bonk - The Game"},
- {html,"../bonk/bonk.txt"}}.
diff --git a/lib/gs/contribs/bonk/bonk.txt b/lib/gs/contribs/bonk/bonk.txt
deleted file mode 100644
index 69c912dbee..0000000000
--- a/lib/gs/contribs/bonk/bonk.txt
+++ /dev/null
@@ -1,30 +0,0 @@
-BONK! In Erlang for You
-by
-LENNART OHMAN & MARCUS ARENDT
-
-After an idea of Mike Darweesh.
-Special thanks to Peter Jansson for creating the bitmaps.
-Ported to GS 1.1 by Markus Torpvret and Anders Dahlin.
-
-
-INSTRUCTIONS
-- Hit as many creatures as possible using the left mouse-button.
-- After every 25 hits You will advance one level. For each level You get one bomb.
-- Pushing the middle or right mouse-button, in any square, drops a bomb which
-wipes out everything.
-- The game ends when 10 creatures has escaped from beeing bonked.
-
-
-ABOUT ERLANG
-Erlang is a programming language for building robust concurrent systems. It is a single assignment, symbolic language with built in concurrency. It provides unique facilities for error handling and for reloading updated modules in running systems. Erlang was designed and implemented by Joe Armstrong, Robert Virding, and Mike Williams at Ellemtel (now Ericsson Utvecklings AB).
-
-Please make enquiries about Erlang to:
-
-Ericsson Software Technology AB
-Erlang Systems
-Torshamnsgatan 39B
-Box 1214
-164 28 Kista
-Sweden
-
-http://www.ericsson.se/erlang \ No newline at end of file
diff --git a/lib/gs/contribs/bonk/bonk_sound.erl b/lib/gs/contribs/bonk/bonk_sound.erl
deleted file mode 100644
index 9a0db80e5d..0000000000
--- a/lib/gs/contribs/bonk/bonk_sound.erl
+++ /dev/null
@@ -1,82 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%
--module(bonk_sound).
--export([start/0]).
-
-start() ->
- random:seed(),
- sounder:start(),
- {ok,Bonk}=sounder:new(lists:append(bonk:bonk_dir(),"sounds/bonk.au")),
- {ok,Ouch}=sounder:new(lists:append(bonk:bonk_dir(),"sounds/ouch!!!.au")),
- {ok,Damn}=sounder:new(lists:append(bonk:bonk_dir(),"sounds/damn.au")),
- {ok,Bomb}=sounder:new(lists:append(bonk:bonk_dir(),"sounds/explosion.au")),
- {ok,Missed}=sounder:new(lists:append(bonk:bonk_dir(),"sounds/missedme.au")),
- {ok,Game_over}=sounder:new(lists:append(bonk:bonk_dir(),"sounds/gameover.au")),
- {ok,New_level}=sounder:new(lists:append(bonk:bonk_dir(),"sounds/level.au")),
- {ok,Music}=sounder:new(lists:append(bonk:bonk_dir(),"sounds/trumpet.au")),
- {ok,Start}=sounder:new(lists:append(bonk:bonk_dir(),"sounds/hehee.au")),
- {ok,BestS}=sounder:new(lists:append(bonk:bonk_dir(),"sounds/praisejesus.au")),
- {ok,HighS}=sounder:new(lists:append(bonk:bonk_dir(),"sounds/yes.au")),
- loop(Bonk, Ouch, Damn, Bomb, Missed, Game_over, New_level,
- Music, Start, BestS, HighS).
-
-
-loop(Bonk, Ouch, Damn, Bomb, Missed, Game_over, New_level, Music, Start, BestS, HighS) ->
- R=random:uniform(1000),
- receive
- bonk ->
- if
- R < 75 -> play_sound(Damn);
- R < 275 -> play_sound(Ouch);
- true -> play_sound(Bonk)
- end;
- bomb -> play_sound(Bomb);
- missed -> play_sound(Missed);
- game_over -> play_sound(Game_over);
- new_level -> play_sound(New_level);
- music -> play_sound(Music);
- start -> play_sound(Start);
- best_score -> play_sound(BestS);
- high_score -> play_sound(HighS);
- quit ->
- sounder:stop(),
- exit(normal)
- end,
- loop(Bonk, Ouch, Damn, Bomb, Missed, Game_over, New_level, Music, Start, BestS, HighS).
-
-play_sound(Snd) ->
- case catch sounder:play(Snd) of
- {'EXIT', _Reason} ->
- io:format("Cannot use audio device!\n"),
- sounder:stop(),
- silent_loop();
- _Other ->
- true
- end.
-
-silent_loop() ->
- receive
- quit ->
- exit(normal);
- _Other ->
- silent_loop()
- end.
diff --git a/lib/gs/contribs/bonk/bonk_square.erl b/lib/gs/contribs/bonk/bonk_square.erl
deleted file mode 100644
index 98af91944b..0000000000
--- a/lib/gs/contribs/bonk/bonk_square.erl
+++ /dev/null
@@ -1,146 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%
--module(bonk_square).
--export([start/1,init/5,alarm/3]).
-
-
-
-start(Bmp) ->
- spawn_link(bonk_square, init, [Bmp, self(),
- random:uniform(10000),
- random:uniform(10000),
- random:uniform(10000)]).
-
-init(Bmp, BoardPid, Seed1, Seed2, Seed3) ->
- random:seed(Seed1,Seed2,Seed3),
- idle(Bmp, BoardPid).
-
-
-idle(Bmp, BoardPid) ->
- receive
- start ->
- Level = 1,
- sleep(Level, Bmp, BoardPid, alarm(sleep_time(Level), wake_up));
- quit ->
- exit(normal);
- _Other ->
- idle(Bmp, BoardPid)
- end.
-
-
-sleep(Level, Bmp, BoardPid, Alarm) ->
- receive
- stop ->
- Alarm ! quit,
- idle(Bmp, BoardPid);
- quit ->
- Alarm ! quit,
- exit(normal);
- {new_level, NewLevel} ->
- sleep(NewLevel, Bmp, BoardPid, Alarm);
- {Alarm, wake_up} ->
- show_me(BoardPid, Bmp),
- show(Level, Bmp, BoardPid, alarm(2500, missed));
- _Other ->
- sleep(Level, Bmp, BoardPid, Alarm)
- end.
-
-
-show(Level, Bmp, BoardPid, Alarm) ->
- receive
- stop ->
- Alarm ! quit,
- idle(Bmp, BoardPid);
- quit ->
- Alarm ! quit,
- exit(normal);
- {new_level, NewLevel} ->
- show(NewLevel, Bmp, BoardPid, Alarm);
- sleep -> % The board was too crowded.
- Alarm ! quit,
- sleep(Level, Bmp, BoardPid, alarm(sleep_time(Level), wake_up));
- bonk ->
- bonk_me(BoardPid, Bmp),
- Alarm ! quit,
- bbmed(Level, Bmp, BoardPid, alarm(1500, hide));
- bomb ->
- bomb_me(BoardPid, Bmp),
- Alarm ! quit,
- bbmed(Level, Bmp, BoardPid, alarm(1000, hide));
- {Alarm, missed} ->
- missed_me(BoardPid, Bmp),
- bbmed(Level, Bmp, BoardPid, alarm(1500, hide));
- _Other ->
- show(Level, Bmp, BoardPid, Alarm)
- end.
-
-%% bonked, bombed or missed
-bbmed(Level, Bmp, BoardPid, Alarm) ->
- receive
- stop ->
- Alarm ! quit,
- idle(Bmp, BoardPid);
- quit ->
- Alarm ! quit,
- exit(normal);
- {new_level, NewLevel} ->
- bbmed(NewLevel, Bmp, BoardPid, Alarm);
- {Alarm, hide} ->
- hide_me(BoardPid, Bmp),
- sleep(Level, Bmp, BoardPid, alarm(sleep_time(Level), wake_up));
- _Other ->
- bbmed(Level, Bmp, BoardPid, Alarm)
- end.
-
-
-show_me(BoardPid, Bmp) ->
- BoardPid ! {show, self(), Bmp}.
-
-hide_me(BoardPid, Bmp) ->
- BoardPid ! {hide, self(), Bmp}.
-
-bonk_me(BoardPid, Bmp) ->
- BoardPid ! {bonked, self(), Bmp}.
-
-bomb_me(BoardPid, Bmp) ->
- BoardPid ! {bombed, self(), Bmp}.
-
-missed_me(BoardPid, Bmp) ->
- BoardPid ! {missed, self(), Bmp}.
-
-
-%% Count sleep time
-
-sleep_time(Level) ->
- random:uniform((19000 div (Level+1))*2+1500).
-
-%% Set an alarm
-
-alarm(Time, Msg) ->
- spawn(bonk_square, alarm, [Time, Msg, self()]).
-
-alarm(Time, Msg, Pid) ->
- receive
- quit -> exit(normal)
- after
- Time -> Pid ! {self(), Msg}
- end.
diff --git a/lib/gs/contribs/bonk/sounder.erl b/lib/gs/contribs/bonk/sounder.erl
deleted file mode 100644
index aabcaa1950..0000000000
--- a/lib/gs/contribs/bonk/sounder.erl
+++ /dev/null
@@ -1,160 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%
--module(sounder).
--export([start/0,play/1,new/1,go/0,stop/0,nosound/0,silent/0]).
--include_lib("kernel/include/file.hrl").
-%%----------------------------------------------------------------------
-%% sounder.erl - An interface to /dev/audio
-%%
-%% Created by: {lennarto,mike}@erix.ericsson.se
-%% Modified by: EV,[email protected]
-%%
-%% Mod: 6 Jun 1996 by [email protected]
-%% The executable sounder will no be looked for in the
-%% same directory as from where sounder.jam is loaded.
-%%
-%%
-%% start() - Returns either: ok ,or: silent ,where silent means
-%% that no audio capabilities exists but the sounder
-%% will work "silently" in order to not break any code.
-%%
-%% stop() - Returns: ok
-%%
-%% new(File) - Tries to load the File. At success, a number refering
-%% to the File is returned that shall be used with send/1.
-%% Otherwise {error,Reason} is returned.
-%%
-%% play(No) - Tries to execute the sound registered with the number No
-%% Returns: ok , or: {error,Reason}
-%%
-%% silent() - Returns: true ,if no audio capabilities exists, else: false
-%%
-%% Note: It is also possible to receive: {error,sounder_not_started}
-%%
-%%----------------------------------------------------------------------
-
-start() ->
- case whereis(sounder) of
- undefined ->
- %% first we check if the workstation has audio capabilities
- case file:read_file_info('/dev/audio') of
- {ok, FI} when FI#file_info.access==read_write ->
- register(sounder, spawn(sounder,go,[])),
- ok;
- _Other ->
- register(sounder, spawn(sounder,nosound,[])),
- silent
- end;
- _Pid ->
- ok
- end.
-
-stop() ->
- catch begin check(),
- sounder ! {stop},
- ok end.
-
-new(File) when is_list(File) -> new(list_to_atom(File));
-new(File) when is_atom(File) ->
- catch begin check(),
- sounder ! {new,File,self()},
- wait_for_ack(sounder) end.
-
-play(No) when is_integer(No) ->
- catch begin check(),
- sounder ! {play, No, self()},
- wait_for_ack(sounder) end.
-
-silent() ->
- catch begin check(),
- sounder ! {play,silent,self()},
- receive {sounder,Answer} -> Answer end end.
-
-go() ->
- Port = open_port({spawn,lists:append(bonk:bonk_dir(), "sounder")},[{packet, 2}]),
- loop(Port).
-
-loop(Port) ->
- receive
- {new, File, From} when is_atom(File) ->
- Port ! {self(),{command,lists:append([0],atom_to_list(File))}},
- From ! {sounder,wait_for_ack(Port)},
- loop(Port);
- {play,silent,From} ->
- From ! {sounder,false},
- loop(Port);
- {play,No,From} when is_integer(No) ->
- Port ! {self(),{command,[No]}},
- From ! {sounder,wait_for_ack(Port)},
- loop(Port);
- {stop} ->
- Port ! {self(),close},
- exit(normal);
- _ ->
- loop(Port)
- end.
-
-%% The application using sounds can check on silence itself
-%% and refrain from playing sounds.
-%% Or it can try to play sounds that will be "consumed in silence"
-
-nosound() ->
- receive
- {new,File,From} when is_atom(File) ->
- From ! {sounder,{ok,silent}},
- nosound();
- {play,silent,From} ->
- From ! {sounder,true},
- nosound();
- {play,No,From} when is_integer(No) ->
- From ! {sounder,{error,no_audio_cap}},
- nosound();
- {stop} ->
- exit(normal);
- _ ->
- nosound()
- end.
-
-wait_for_ack(sounder) ->
- receive {sounder,Res} -> Res end;
-wait_for_ack(Port) when is_port(Port) ->
- receive
- {Port,{data,"ok"}} ->
- ok;
- {Port,{data,[No]}} ->
- {ok,No};
- {Port,{data,Msg}} ->
- {error,list_to_atom(Msg)};
- {'EXIT',Port,_} ->
- exit(port_exited)
- end.
-
-check() ->
- case whereis(sounder) of
- Pid when is_pid(Pid) ->
- ok;
- undefined ->
- throw({error,sounder_not_started})
- end.
-
-
-
diff --git a/lib/gs/contribs/bonk/sounds/bonk.au b/lib/gs/contribs/bonk/sounds/bonk.au
deleted file mode 100644
index 5e6518898b..0000000000
--- a/lib/gs/contribs/bonk/sounds/bonk.au
+++ /dev/null
Binary files differ
diff --git a/lib/gs/contribs/bonk/sounds/damn.au b/lib/gs/contribs/bonk/sounds/damn.au
deleted file mode 100644
index 6117506fb4..0000000000
--- a/lib/gs/contribs/bonk/sounds/damn.au
+++ /dev/null
Binary files differ
diff --git a/lib/gs/contribs/bonk/sounds/explosion.au b/lib/gs/contribs/bonk/sounds/explosion.au
deleted file mode 100644
index 78a6964f1a..0000000000
--- a/lib/gs/contribs/bonk/sounds/explosion.au
+++ /dev/null
Binary files differ
diff --git a/lib/gs/contribs/bonk/sounds/gameover.au b/lib/gs/contribs/bonk/sounds/gameover.au
deleted file mode 100644
index ca7628f3c6..0000000000
--- a/lib/gs/contribs/bonk/sounds/gameover.au
+++ /dev/null
Binary files differ
diff --git a/lib/gs/contribs/bonk/sounds/hehee.au b/lib/gs/contribs/bonk/sounds/hehee.au
deleted file mode 100644
index 10cd16b596..0000000000
--- a/lib/gs/contribs/bonk/sounds/hehee.au
+++ /dev/null
Binary files differ
diff --git a/lib/gs/contribs/bonk/sounds/level.au b/lib/gs/contribs/bonk/sounds/level.au
deleted file mode 100644
index 0508c2a6ae..0000000000
--- a/lib/gs/contribs/bonk/sounds/level.au
+++ /dev/null
Binary files differ
diff --git a/lib/gs/contribs/bonk/sounds/missedme.au b/lib/gs/contribs/bonk/sounds/missedme.au
deleted file mode 100644
index 4c07c9d428..0000000000
--- a/lib/gs/contribs/bonk/sounds/missedme.au
+++ /dev/null
Binary files differ
diff --git a/lib/gs/contribs/bonk/sounds/music.au b/lib/gs/contribs/bonk/sounds/music.au
deleted file mode 100644
index ead6ec79b2..0000000000
--- a/lib/gs/contribs/bonk/sounds/music.au
+++ /dev/null
Binary files differ
diff --git a/lib/gs/contribs/bonk/sounds/ouch!!!.au b/lib/gs/contribs/bonk/sounds/ouch!!!.au
deleted file mode 100644
index 78bcf48074..0000000000
--- a/lib/gs/contribs/bonk/sounds/ouch!!!.au
+++ /dev/null
Binary files differ
diff --git a/lib/gs/contribs/bonk/sounds/praisejesus.au b/lib/gs/contribs/bonk/sounds/praisejesus.au
deleted file mode 100644
index e299bf66d6..0000000000
--- a/lib/gs/contribs/bonk/sounds/praisejesus.au
+++ /dev/null
Binary files differ
diff --git a/lib/gs/contribs/bonk/sounds/trumpet.au b/lib/gs/contribs/bonk/sounds/trumpet.au
deleted file mode 100644
index 2f551b436a..0000000000
--- a/lib/gs/contribs/bonk/sounds/trumpet.au
+++ /dev/null
Binary files differ
diff --git a/lib/gs/contribs/bonk/sounds/yes.au b/lib/gs/contribs/bonk/sounds/yes.au
deleted file mode 100644
index c1ce7dfb69..0000000000
--- a/lib/gs/contribs/bonk/sounds/yes.au
+++ /dev/null
Binary files differ
diff --git a/lib/gs/contribs/cols/Makefile b/lib/gs/contribs/cols/Makefile
deleted file mode 100644
index 34a900e5ab..0000000000
--- a/lib/gs/contribs/cols/Makefile
+++ /dev/null
@@ -1,103 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1996-2012. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-
-#
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../../vsn.mk
-VSN=$(GS_VSN)
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/gs-$(VSN)/contribs
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-
-MODULES= \
- cols \
- highscore
-
-HRL_FILES=
-
-ERL_FILES= $(MODULES:%=%.erl)
-
-TARGET_FILES= $(MODULES:%=../ebin/%.$(EMULATOR)) $(TARGET_TOOLBOX_FILES)
-
-TOOLNAME = cols
-
-EXTRA_FILES=
-TOOLBOX_FILES= $(TOOLNAME).tool $(TOOLNAME).gif help.gif
-TARGET_TOOLBOX_FILES= $(TOOLBOX_FILES:%=$(EBIN)/%)
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-ERL_COMPILE_FLAGS +=
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-
-debug opt: $(TARGET_FILES)
-
-docs:
-
-clean:
- rm -f $(TARGET_FILES)
- rm -f core
-
-# ----------------------------------------------------
-# Special Build Targets
-# ----------------------------------------------------
-
-$(EBIN)/$(TOOLNAME).gif: $(TOOLNAME).gif
- $(gen_verbose)rm -f $@
- $(V_at)cp $(TOOLNAME).gif $@
-
-$(EBIN)/$(TOOLNAME).tool: $(TOOLNAME).tool
- $(gen_verbose)rm -f $@
- $(V_at)cp $(TOOLNAME).tool $@
-
-$(EBIN)/help.gif: help.gif
- $(gen_verbose)rm -f $@
- $(V_at)cp help.gif $@
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-release_spec: opt
- $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
- $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
- $(INSTALL_DIR) "$(RELSYSDIR)/cols/bitmaps"
- $(INSTALL_DATA) $(BITMAPS) $(TOOLBOX_FILES) "$(RELSYSDIR)/cols/bitmaps"
- $(INSTALL_DIR) "$(RELSYSDIR)/cols"
- $(INSTALL_DATA) $(ERL_FILES) $(EXTRA_FILES) "$(RELSYSDIR)/cols"
-
-release_docs_spec:
-
diff --git a/lib/gs/contribs/cols/cols.erl b/lib/gs/contribs/cols/cols.erl
deleted file mode 100644
index 265f2b6ee8..0000000000
--- a/lib/gs/contribs/cols/cols.erl
+++ /dev/null
@@ -1,625 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%
--module(cols).
--compile([{nowarn_deprecated_function,{gs,config,2}},
- {nowarn_deprecated_function,{gs,create,3}},
- {nowarn_deprecated_function,{gs,create,4}},
- {nowarn_deprecated_function,{gs,destroy,1}},
- {nowarn_deprecated_function,{gs,read,2}},
- {nowarn_deprecated_function,{gs,start,0}}]).
-
--export([start/0, init/0]).
-
-%% internal export.
--export([make_board_elem/3]).
-
-%%======================================================================
-%% Contents
-%%=====================
-%% 1. The actual program
-%% 2. Graphics
-%% 3. Data structures and stuff
-%% 4. Lambdas
-%%======================================================================
-
-
--define(COLORS, {red,green,blue,grey,yellow,{66,153,130}}).
--define(HIGHFILE, "./cols.high").
--define(HEIGHT, 17).
--define(LEFT, 50).
--define(SIZE, 15).
--define(VERSION, "v0.9").
--define(WIDTH, 8).
-
--record(state, {bit,board,nextbit,ticks, score=0}).
-%%----------------------------------------------------------------------
-%% Consists of three boxes.
-%%----------------------------------------------------------------------
--record(bit, {x,y,topColor, middleColor, bottomColor,
- top_gsobj,mid_gsobj,bot_gsobj}).
-
-%%======================================================================
-%% 1. The actual program
-%%======================================================================
-
-start() ->
- spawn_link(cols,init,[]).
-
-init() ->
- make_graphics(),
- {A,B,C} = erlang:now(),
- random:seed(A,B,C),
- NextBit = make_bit(),
- Board = make_screen_board(),
- S = #state{bit=make_bit(), board=Board, ticks=update_timer(1),
- score=make_score(), nextbit=new_bit_xy(NextBit, -2,5)},
- gs:config(win, [{map, true}]),
- loop(S).
-
-make_graphics() ->
- G = gs:start(),
- H = ?HEIGHT*?SIZE,
- W = ?WIDTH*?SIZE,
- BotMargin = 100,
- gs:create(window, win, G, [{destroy,true},{map, true},{title, "cols"},
- {height, H+BotMargin}, {width, W+?LEFT+10},
- {bg, grey},{keypress,true}]),
- gs:create(canvas, can, win, [{bg, black},
- {height, H+BotMargin},
- {width, W+?LEFT+20}]),
- gs:create(text, can, [{text, "Next"}, {coords, [{5, 45}]}, {fg, red}]),
- gs:create(image, help, can, [{coords,[{5,7}]},
- {load_gif, dir() ++ "/help.gif"},
- {buttonpress,true}]),
- draw_borders().
-
-loop(State) ->
- receive
- Event -> loop(update(Event, State))
- end.
-
-%%----------------------------------------------------------------------
-%% How fast speed should be doubled
-%%----------------------------------------------------------------------
--define(DBL_TICKS, 300).
-
-update_timer(Ticks) ->
- K = 0.001/?DBL_TICKS,
- M = 1.001-K,
- Q = K*Ticks+M,
- Timeout = round(1/math:log(Q)),
- timer:send_after(Timeout, self(), fall_timeout),
- Ticks+1.
-
-add_score({ScoreObj, NScore}, DScore) ->
- NScore2 = NScore + DScore,
- gs:config(ScoreObj, [{text, io_lib:format("Score: ~w", [NScore2])}]),
- {ScoreObj, NScore2}.
-
-
-update({gs,_Obj,keypress,_Data, ['Left'|_]}, State) ->
- #state{bit=Bit, board = Board} = State,
- #bit{x=X,y=Y} = Bit,
- if X > 0 ->
- case is_board_empty(Board, X-1,Y) of
- true ->
- State#state{bit=new_bit_xy(Bit, X-1, Y)};
- false ->
- State
- end;
- true -> State
- end;
-
-update({gs,_Obj,keypress,_Data, ['Right'|_]}, State) ->
- #state{bit=Bit, board = Board} = State,
- #bit{x=X,y=Y} = Bit,
- if X < ?WIDTH - 1 ->
- case is_board_empty(Board, X+1, Y) of
- true ->
- State#state{bit=new_bit_xy(Bit, X+1, Y)};
- false ->
- State
- end;
- true -> State
- end;
-
-update({gs,_Obj,keypress,_Data, ['Up'|_]}, State) ->
- State#state{bit=shift_bits(State#state.bit)};
-
-update({gs,_Obj,keypress,_Data, [Key|_]}, State) ->
- case drop_key(Key) of
- true ->
- #state{bit=Bit, board=Board, score=Score} = State,
- #bit{x=X,y=Y} = Bit,
- {NewX, NewY, NewScore} = drop(X,Y,Score,Board),
- fasten_bit(State#state{bit=new_bit_xy(Bit,NewX, NewY),
- score=NewScore});
- false -> State
- end;
-
-update(fall_timeout, State) ->
- #state{bit=Bit, board=Board, ticks = Ticks, score=Score} = State,
- NewY = Bit#bit.y+1,
- X = Bit#bit.x,
- case is_fall_ok(Board, X, NewY) of
- true ->
- State#state{bit=new_bit_xy(Bit, X, NewY),
- ticks=update_timer(Ticks), score=add_score(Score, 1)};
- false ->
- S1 = fasten_bit(State),
- S1#state{ticks=update_timer(Ticks)}
- end;
-
-update({gs,_,destroy,_,_}, _State) ->
- exit(normal);
-
-update({gs,help,buttonpress,_,_}, State) ->
- show_help(),
- State;
-
-update(OtherEvent, State) ->
- ok=io:format("got other! ~w~n", [OtherEvent]), State.
-
-drop_key('Down') -> true;
-drop_key(space) -> true;
-drop_key(_) -> false.
-
-is_board_empty(Board, X, Y) ->
- case {color_at(Board, X, Y),
- color_at(Board, X, Y + 1),
- color_at(Board, X, Y + 2)} of
- {black, black, black} -> true;
- _ -> false
- end.
-
-%%----------------------------------------------------------------------
-%% Returns: NewState
-%%----------------------------------------------------------------------
-fasten_bit(State) ->
- #state{board=Board, bit=Bit, nextbit=NextBit, score=Score} = State,
- #bit{x=X,y=Y,topColor=C1,middleColor=C2,bottomColor=C3} = Bit,
- B1 = update_screen_element(Board, X, Y, C1),
- B2 = update_screen_element(B1, X, Y+1, C2),
- B3 = update_screen_element(B2, X, Y+2, C3),
- destroy_bit(Bit),
- #bit{topColor=NC1,middleColor=NC2,bottomColor=NC3} = NextBit,
- {B4, ExtraScore} = erase_bits(B3, [{X,Y},{X,Y+1},{X,Y+2}], 0),
- NewBit = make_bit(NC1,NC2,NC3),
- case is_board_empty(B4, NewBit#bit.x, NewBit#bit.y) of
- true ->
- State#state{score=add_score(Score, ExtraScore),
- bit=NewBit, nextbit=new_colors(NextBit),board=B4};
- false ->
- {_GsObj,Score2}=State#state.score,
- highscore:run(Score2,?HIGHFILE),
- exit(normal)
- end.
-
-%%----------------------------------------------------------------------
-%% Args: Check: list of {X,Y} to check.
-%% Returns: {NewBoard, ExtraScore}
-%%----------------------------------------------------------------------
-erase_bits(Board, Checks, ExtraScore) ->
- ElemsToDelete = elems2del(Checks,Board,[]),
- NDel = length(ElemsToDelete),
- if
- NDel > 0 ->
- Board2 = delete_elems(Board, ElemsToDelete),
- {NewBoard, NewCheck} = fall_down(Board2, ElemsToDelete),
- if NDel > 3 ->
- {B,ES}=erase_bits(NewBoard,NewCheck,ExtraScore+2*NDel),
- {NewBoard2, NewCheck2} = bonus(B, NewCheck),
- erase_bits(NewBoard2, NewCheck2, ES);
- true ->
- erase_bits(NewBoard, NewCheck, 2*NDel)
- end;
- true -> {Board, ExtraScore}
- end.
-
-bonus(Board, Check) ->
- Cols = collect_bottom_bits(0,Board),
- NewBoard = randomize_columns(5, Board, Cols),
- NewCheck = update_check(Check, Cols),
- {NewBoard, NewCheck}.
-
-randomize_columns(0, Board, _) -> Board;
-randomize_columns(N, Board, Cols) ->
- NewBoard = randomize_columns(Cols,Board),
- randomize_columns(N-1, NewBoard, Cols).
-
-randomize_columns([],Board) -> Board;
-randomize_columns([X|Xs],Board) ->
- flush(),
- timer:sleep(50),
- randomize_columns(Xs,update_screen_element(Board,X,?HEIGHT-1,rndColor())).
-
-%%----------------------------------------------------------------------
-%% Returns: NewBoard
-%%----------------------------------------------------------------------
-delete_elems(Board, Elems2Del) ->
- OrgObjs = org_objs(Elems2Del,Board),
- visual_effect(?SIZE, OrgObjs),
- NewBoard = update_board(Elems2Del, Board),
- put_back(OrgObjs),
- NewBoard.
-
-visual_effect(0,_OrgObjs) -> done;
-visual_effect(Size,OrgObjs) ->
- set_size(OrgObjs,Size),
- flush(),
- timer:sleep(20),
- visual_effect(Size-1,OrgObjs).
-
-set_size([],_Size) -> done;
-set_size([{GsObj,[{X1,Y1},{_X2,_Y2}]}|T],Size) ->
- gs:config(GsObj, [{coords, [{X1,Y1},{X1+Size,Y1+Size}]}]),
- set_size(T,Size).
-
-%%----------------------------------------------------------------------
-%% Note: Loop over columns where something is removed only. (efficiency)
-%% Returns: {ReversedNewColumns (perhaps shorter), Checks}
-%% cols:fall_column([a,b,black,black,c,f,black,d,black], 3, 15, [], []).
-%% should return: {[a,b,c,f,d],[{3,11},{3,12},{3,13}]}
-%%----------------------------------------------------------------------
-fall_column([], _X, _Y, ColumnAcc, ChecksAcc) ->
- {ColumnAcc, ChecksAcc};
-fall_column([black|Colors], X, Y, ColumnAcc, ChecksAcc) ->
- case find_box(Colors) of
- false -> {ColumnAcc, ChecksAcc};
- NewColors when is_list(NewColors) ->
- fall_one_step(NewColors, X, Y, ColumnAcc, ChecksAcc)
- end;
-fall_column([Color|Colors], X, Y, ColumnAcc, ChecksAcc) ->
- fall_column(Colors, X, Y-1, [Color | ColumnAcc], ChecksAcc).
-
-find_box([]) -> false;
-find_box([black|Colors]) ->
- find_box(Colors);
-find_box([Color|Colors]) -> [Color|Colors].
-
-%%----------------------------------------------------------------------
-%% Enters: ([a,b, , ,c,d], 3, 8, Q)
-%% Leaves: ([b,a|Q], [ , , ,c,d], 10, [{3,8},{4,9}])
-%%----------------------------------------------------------------------
-fall_one_step([], X, Y, ColumnAcc, Checks) ->
- fall_column([], X, Y, ColumnAcc, Checks);
-fall_one_step([black|Colors], X, Y, ColumnAcc, Checks) ->
- fall_column([black|Colors], X, Y, ColumnAcc, Checks);
-fall_one_step([Color|Colors], X, Y, ColumnAcc, Checks) ->
- fall_one_step(Colors, X, Y-1, [Color|ColumnAcc],[{X,Y}|Checks]).
-
-%%----------------------------------------------------------------------
-%% Returns: {NewBoard, NewChecks}
-%%----------------------------------------------------------------------
-fall_down(Board1, Elems2Del) ->
- UpDatedCols = updated_cols(Elems2Del, []),
- fall_column(UpDatedCols, Board1, []).
-
-fall_column([], NewBoard, NewChecks) -> {NewBoard, NewChecks};
-fall_column([X|Xs], BoardAcc, ChecksAcc) ->
- OrgColumn = boardcolumn_to_tuple(BoardAcc, X),
- Column = columntuple_to_list(OrgColumn),
- {NewColumn, NewChecksAcc} = fall_column(Column, X,?HEIGHT-1,[],ChecksAcc),
- NewBoardAcc =
- set_board_column(BoardAcc,X,new_column_list(NewColumn,OrgColumn)),
- fall_column(Xs,NewBoardAcc,NewChecksAcc).
-
-new_column_list(NewColumn, ColumnTuple) ->
- Nempty = ?HEIGHT - length(NewColumn),
- L = make_list(black, Nempty) ++ NewColumn,
- new_column_list(L, 1, ColumnTuple).
-
-new_column_list([H|T], N, Tuple) ->
- {GsObj, Color} = element(N, Tuple),
- [update_screen_element({GsObj, Color},H) | new_column_list(T, N+1, Tuple)];
-new_column_list([], _, _) -> [].
-
-
-%%----------------------------------------------------------------------
-%% Returns: a reversed list of colors.
-%%----------------------------------------------------------------------
-columntuple_to_list(ColumnTuple) when is_tuple(ColumnTuple) ->
- columntuple_to_list(tuple_to_list(ColumnTuple),[]).
-
-columntuple_to_list([],Acc) -> Acc;
-columntuple_to_list([{_GsObj, Color}|T],Acc) ->
- columntuple_to_list(T,[Color|Acc]).
-
-%%======================================================================
-%% 2. Graphics
-%%======================================================================
-
-make_bit() ->
- make_bit(rndColor(),rndColor(),rndColor()).
-
-make_bit(Tc,Mc,Bc) ->
- X = ?WIDTH div 2,
- Y = 0,
- #bit{x=X,y=Y,topColor= Tc, middleColor=Mc, bottomColor=Bc,
- top_gsobj = make_box(X,Y,Tc), mid_gsobj=make_box(X,Y+1,Mc),
- bot_gsobj=make_box(X,Y+2,Bc)}.
-
-new_colors(Bit) ->
- #bit{top_gsobj=T,mid_gsobj=M,bot_gsobj=B} = Bit,
- Tc = rndColor(),
- Mc = rndColor(),
- Bc = rndColor(),
- gs:config(T, [{fill, Tc}]),
- gs:config(M, [{fill, Mc}]),
- gs:config(B, [{fill, Bc}]),
- Bit#bit{topColor= Tc, middleColor=Mc, bottomColor=Bc}.
-
-new_bit_xy(Bit, NewX, NewY) ->
- #bit{x=X,y=Y,top_gsobj=T,mid_gsobj=M,bot_gsobj=B} = Bit,
- Dx = (NewX - X) * ?SIZE,
- Dy = (NewY - Y) * ?SIZE,
- gs:config(T, [{move, {Dx, Dy}}]),
- gs:config(M, [{move, {Dx, Dy}}]),
- gs:config(B, [{move, {Dx, Dy}}]),
- Bit#bit{x=NewX, y=NewY}.
-
-destroy_bit(#bit{top_gsobj=T,mid_gsobj=M,bot_gsobj=B}) ->
- gs:destroy(T),
- gs:destroy(M),
- gs:destroy(B).
-
-shift_bits(Bit) ->
- #bit{topColor=C1,middleColor=C2,bottomColor=C3,
- top_gsobj=T,mid_gsobj=M,bot_gsobj=B} = Bit,
- gs:config(T, {fill,C2}),
- gs:config(M, {fill,C3}),
- gs:config(B, {fill,C1}),
- Bit#bit{topColor=C2, middleColor=C3, bottomColor=C1}.
-
-rndColor() ->
- Siz = size(?COLORS),
- element(random:uniform(Siz), ?COLORS).
-
-make_score() ->
- {gs:create(text, can, [{text, "Score: 0"}, {fg, red},
- {coords, [{5,?HEIGHT*?SIZE+10}]}]), 0}.
-
-make_screen_board() ->
- xy_loop({cols,make_board_elem}, make_board(), ?WIDTH, ?HEIGHT).
-
-make_board_elem(X,Y,Board) ->
- set_board_element(Board,X,Y,{make_box(X,Y,black),black}).
-
-flush() -> gs:read(can, bg).
-
-draw_borders() ->
- BotY = ?HEIGHT*?SIZE,
- RightX = ?LEFT + ?SIZE*?WIDTH,
- LeftX = ?LEFT - 1,
- gs:create(line,can,[{coords,[{LeftX,0},{LeftX,BotY}]},{fg,white}]),
- gs:create(line,can,[{coords,[{LeftX,BotY},{RightX,BotY}]},{fg,white}]),
- gs:create(line,can,[{coords,[{RightX,0},{RightX, BotY}]}, {fg,white}]).
-
-update_screen_element(ScrBoard, X, Y, Color) ->
- case board_element(ScrBoard,X,Y) of
- {_GsObj, Color} ->
- ScrBoard; % don't have to update screen
- {GsObj, _ScreenColor} ->
- gs:config(GsObj, color_args(Color)),
- set_board_element(ScrBoard, X, Y, {GsObj, Color})
- end.
-
-update_screen_element(ScrElem, Color) ->
- case ScrElem of
- {_GsObj, Color} ->
- ScrElem; % don't have to update screen
- {GsObj, _ScreenColor} ->
- gs:config(GsObj, color_args(Color)),
- {GsObj, Color}
- end.
-
-
-color_args(black) -> [{fg,black},{fill,black}];
-color_args(Color) -> [{fg,white},{fill,Color}].
-
-%%======================================================================
-%% 3. Data structures and stuff
-%%======================================================================
-
-xy_loop(Fun, Acc, XMax, YMax) ->
- xy_loop(Fun, Acc, 0, 0, XMax, YMax).
-
-xy_loop(_Fun, Acc, _X, YMax, _XMax, YMax) -> Acc;
-xy_loop(Fun, Acc, XMax, Y, XMax, YMax) ->
- xy_loop(Fun, Acc, 0, Y+1, XMax, YMax);
-xy_loop(Fun, Acc, X, Y, XMax, YMax) ->
- xy_loop(Fun, apply(Fun, [X, Y,Acc]), X+1,Y,XMax, YMax).
-
-%%----------------------------------------------------------------------
-%% Returns: a sorted list of {X,Y} to delete.
-%% Pre: PrevDelElems is sorted.
-%%----------------------------------------------------------------------
-erase_bits_at(Board, PrevDelElems, X,Y) ->
- C = color_at(Board, X, Y),
- erase_bits_at([vert, horiz, slash, backslash],X,Y,C,Board,PrevDelElems).
-
-erase_bits_at([], _X,_Y,_C,_Board, Elems2Del) -> Elems2Del;
-erase_bits_at([Dir|Ds],X,Y,C,Board, Elems2DelAcc) ->
- Dx = dx(Dir),
- Dy = dy(Dir),
- DelElems = lists:append(check_dir(Board, X-Dx,Y-Dy,-Dx,-Dy,C),
- check_dir(Board, X,Y,Dx,Dy,C)),
- N_in_a_row = length(DelElems),
- if N_in_a_row >= 3 ->
- erase_bits_at(Ds,X,Y,C,Board,
- ordsets:union(lists:sort(DelElems),Elems2DelAcc));
- true -> erase_bits_at(Ds,X,Y,C,Board,Elems2DelAcc)
- end.
-
-dx(vert) -> 0;
-dx(horiz) -> 1;
-dx(slash) -> 1;
-dx(backslash) -> -1.
-
-dy(vert) -> -1;
-dy(horiz) -> 0;
-dy(slash) -> -1;
-dy(backslash) -> -1.
-
-
-%%----------------------------------------------------------------------
-%% Returns: list of {X,Y} to delete.
-%%----------------------------------------------------------------------
-check_dir(Board, X, Y, Dx, Dy, Color)
- when X >= 0, X < ?WIDTH, Y >= 0, Y < ?HEIGHT ->
- case color_at(Board, X, Y) of
- Color ->
- [{X,Y} | check_dir(Board, X+Dx, Y+Dy, Dx, Dy, Color)];
- _OtherColor ->
- []
- end;
-check_dir(_Board, _X, _Y, _Dx, _Dy, _Color) -> [].
-
-make_box(X, Y, Color) ->
- make_box(X, Y, 1, 1, Color).
-
-%%----------------------------------------------------------------------
-%% Returns: GsObj
-%%----------------------------------------------------------------------
-make_box(X, Y, Height, Width, Color) ->
- Opts = if Color == black -> [{fg, black}, {fill, black}];
- true -> [{fill, Color}, {fg, white}] end,
- gs:create(rectangle, can, [{coords, [{?LEFT + X * ?SIZE, Y * ?SIZE},
- {?LEFT + X * ?SIZE + (?SIZE*Width)-1,
- Y * ?SIZE + (?SIZE*Height)-1}]}|Opts]).
-
-is_fall_ok(_Board, _NewX, NewY) when NewY+2 >= ?HEIGHT -> false;
-is_fall_ok(Board, NewX, NewY) ->
- case color_at(Board, NewX, NewY+2) of
- black ->
- true;
- _ -> false
- end.
-
-color_at(Board, X, Y) ->
- {_GsObj, Color} = board_element(Board, X, Y),
- Color.
-
-
-%%----------------------------------------------------------------------
-%% X:0..?WIDTH-1, Y:0..?HEIGHT
-%%----------------------------------------------------------------------
-make_board() ->
- list_to_tuple(make_list(make_column(), ?WIDTH)).
-
-board_element(Board, X, Y) ->
- element(Y+1, element(X+1, Board)).
-
-set_board_element(Board, X, Y, NewValue) ->
- Col = element(X+1, Board),
- NewCol=setelement(Y+1,Col, NewValue),
- setelement(X+1, Board, NewCol).
-
-make_column() ->
- list_to_tuple(make_list(black, ?HEIGHT)).
-
-make_list(_Elem, 0) -> [];
-make_list(Elem, N) -> [Elem|make_list(Elem,N-1)].
-
-boardcolumn_to_tuple(Board, X) ->
- element(X+1, Board).
-
-set_board_column(Board, X, NewCol) when length(NewCol) == ?HEIGHT ->
- setelement(X+1, Board, list_to_tuple(NewCol)).
-
-show_help() ->
- W = gs:create(window, win, [{title, "cols Help"}, {width, 300},
- {height,300}, {map, true}]),
- gs:create(label, W, [{x,0},{y,0},{height, 200},{width,300},{justify,center},
- {label, {text,
- "cols $Revision: 1.23 $"
- "\nby\n"
- "Klas Eriksson, [email protected]\n\n"
- "Help: Use arrows and space keys.\n"
- " Try to get 3 in-a-row.\n"
- " More than 3 gives bonus."}}]),
- B=gs:create(button, W, [{x,100},{y,250}, {label, {text, "Dismiss"}}]),
- receive
- {gs, B, click, _, _} -> ok
- end,
- gs:destroy(W).
-
-%%======================================================================
-%% 4. Lambdas
-%%======================================================================
-
-drop(X,Y,Score,Board) ->
- case is_fall_ok(Board, X, Y+1) of
- true -> drop(X,Y+1,add_score(Score, 1),Board);
- false -> {X,Y, Score}
- end.
-
-elems2del([], _Board,Elems2DelAcc) -> Elems2DelAcc;
-elems2del([{X,Y}|Checks],Board,Elems2DelAcc) ->
- NewElems2DelAcc = ordsets:union(erase_bits_at(Board,Elems2DelAcc,X,Y),
- Elems2DelAcc),
- elems2del(Checks,Board,NewElems2DelAcc).
-
-collect_bottom_bits(?WIDTH,_Board) -> [];
-collect_bottom_bits(X,Board) ->
- case color_at(Board, X, ?HEIGHT-1) of
- black -> collect_bottom_bits(X+1,Board);
- _AcolorHere -> [X|collect_bottom_bits(X+1,Board)]
- end.
-
-update_check(_Check,[]) -> [];
-update_check(Check,[X|Xs]) ->
- case lists:member({X, ?HEIGHT-1}, Check) of
- true -> update_check(Check,Xs);
- false -> [{X, ?HEIGHT-1}|update_check(Check,Xs)]
- end.
-
-org_objs([],_Board) -> [];
-org_objs([{X,Y}|XYs],Board) ->
- {GsObj, _Color} = board_element(Board, X, Y),
- [{GsObj, lists:sort(gs:read(GsObj, coords))}|org_objs(XYs,Board)].
-
-update_board([],Board) -> Board;
-update_board([{X,Y}|XYs], Board) ->
- update_board(XYs,update_screen_element(Board, X, Y, black)).
-
-put_back([]) -> done;
-put_back([{GsObj, Coords}|Objs]) ->
- gs:config(GsObj, [{coords, Coords}]),
- put_back(Objs).
-
-updated_cols([], UpdColsAcc) -> UpdColsAcc;
-updated_cols([{X,_Y}|XYs], UpdColsAcc) ->
- case lists:member(X,UpdColsAcc) of
- true -> updated_cols(XYs,UpdColsAcc);
- false -> updated_cols(XYs,[X|UpdColsAcc])
- end.
-
-%% This is not an application so we don't have their way of knowing
-%% a private data directory where the GIF files are located (this directory).
-%% We can find GS and makes it relative from there /kgb
-
--define(EbinFromGsPriv,"../contribs/ebin").
-
-dir()->
- GsPrivDir = code:priv_dir(gs),
- filename:join(GsPrivDir,?EbinFromGsPriv).
diff --git a/lib/gs/contribs/cols/cols.gif b/lib/gs/contribs/cols/cols.gif
deleted file mode 100644
index 96e7c1ed4a..0000000000
--- a/lib/gs/contribs/cols/cols.gif
+++ /dev/null
Binary files differ
diff --git a/lib/gs/contribs/cols/cols.tool b/lib/gs/contribs/cols/cols.tool
deleted file mode 100644
index 673c3d8efa..0000000000
--- a/lib/gs/contribs/cols/cols.tool
+++ /dev/null
@@ -1,5 +0,0 @@
-{version,"0.1"}.
-{{tool,"Cols"},
- {start,{cols,start,[]}},
- {icon,"cols.gif"},
- {message,"Cols - The Game"}}.
diff --git a/lib/gs/contribs/cols/help.gif b/lib/gs/contribs/cols/help.gif
deleted file mode 100644
index 59baef1fec..0000000000
--- a/lib/gs/contribs/cols/help.gif
+++ /dev/null
Binary files differ
diff --git a/lib/gs/contribs/cols/highscore.erl b/lib/gs/contribs/cols/highscore.erl
deleted file mode 100644
index 94f68a043a..0000000000
--- a/lib/gs/contribs/cols/highscore.erl
+++ /dev/null
@@ -1,103 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%
--module(highscore).
--compile([{nowarn_deprecated_function,{gs,button,2}},
- {nowarn_deprecated_function,{gs,create,3}},
- {nowarn_deprecated_function,{gs,destroy,1}},
- {nowarn_deprecated_function,{gs,grid,2}},
- {nowarn_deprecated_function,{gs,read,2}},
- {nowarn_deprecated_function,{gs,start,0}},
- {nowarn_deprecated_function,{gs,window,2}}]).
-
--export([run/2]).
-
-run(NScore, File) ->
- Scores = read_scores(File),
- case find_pos(NScore, 1, Scores) of
- false ->
- display(Scores);
- Pos ->
- NewScores = new_highscore(Scores, Pos, NScore),
- write_scores(NewScores,File),
- display(NewScores)
- end.
-
-
-new_highscore(Scores, Pos, NScore) ->
- Txt = io_lib:format("You entered position ~w", [Pos]),
- W = gs:create(window, gs:start(), [{width, 200},{height, 110},{map,true},
- {title, "New Highscore!!!"}]),
- gs:create(label, W, [{label, {text, Txt}}, {x, 0}, {y,0}, {align, center},
- {width, 190},{height, 30}]),
- Entry = gs:create(entry, W, [{x, 0}, {y, 40}, {height, 30}, {width, 200}]),
- Ok = gs:create(button, W, [{label, {text, "Ok"}}, {x, 40}, {y, 75}]),
- receive
- {gs, Ok, click, _,_} ->
- T = gs:read(Entry, text),
- gs:destroy(W),
- lists:sublist(lists:reverse(
- lists:keysort(1, [{NScore, T} | Scores])), 1, 10)
- end.
-
-
-
-read_scores(File) ->
- case file:read_file(File) of
- {ok, Bin} -> binary_to_term(Bin);
- {error, _Reason} ->
- mk_empty_high(10)
- end.
-
-mk_empty_high(0) -> [];
-mk_empty_high(N) -> [{N,"Erlang"}|mk_empty_high(N-1)].
-
-find_pos(_NScore, _N, []) -> false;
-find_pos(NScore, N, [{Score, _Name} | Scores]) when Score > NScore ->
- find_pos(NScore, N+1, Scores);
-find_pos(_NScore, N, _) -> N.
-
-write_scores(Scores,File) ->
- file:write_file(File, term_to_binary(Scores)).
-
-display(Scores) ->
- Win = gs:window(gs:start(), [{width, 300},{height, 250},{map,true},
- {title, "Highscores"}]),
- {W,H} = gs:read(Win,{font_wh,{{screen,12},"aaaaaaa"}}),
- G = gs:grid(Win,[{rows,{1,11}},{columnwidths,[W,4*W]},{hscroll,false},
- {width, 300},{height, 220},{vscroll,false},
- {cellheight,H+2},{font,{screen,12}}]),
- insert_scores(G,2,Scores),
- Ok = gs:button(Win, [{label, {text, "OK"}}, {x, 100}, {y, 220}]),
- receive
- {gs, Ok, click, _,_} -> gs:destroy(Win),
- ok
- end.
-
-insert_scores(Grid,_N,[]) ->
- gs:create(gridline,Grid,[{row,1},{font,{screen,bold,12}},
- {text,{1,"SCORE"}},{text,{2,"NAME"}}]);
-
-insert_scores(Grid,Row,[{Score,Name}|Ss]) ->
- gs:create(gridline,Grid,[{row,Row},{text,{1,io_lib:format("~w",[Score])}},
- {text,{2,Name}}]),
- insert_scores(Grid,Row+1,Ss).
-
diff --git a/lib/gs/contribs/ebin/.gitignore b/lib/gs/contribs/ebin/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/gs/contribs/ebin/.gitignore
+++ /dev/null
diff --git a/lib/gs/contribs/mandel/Makefile b/lib/gs/contribs/mandel/Makefile
deleted file mode 100644
index b806cc7801..0000000000
--- a/lib/gs/contribs/mandel/Makefile
+++ /dev/null
@@ -1,101 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1996-2012. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-
-#
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../../vsn.mk
-VSN=$(GS_VSN)
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/gs-$(VSN)/contribs
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-
-MODULES= \
- mandel
-
-HRL_FILES=
-
-ERL_FILES= $(MODULES:%=%.erl)
-
-TARGET_FILES= $(MODULES:%=../ebin/%.$(EMULATOR)) $(TARGET_TOOLBOX_FILES)
-
-TOOLNAME = mandel
-
-EXTRA_FILES= $(TOOLNAME).html
-TOOLBOX_FILES= $(TOOLNAME).tool $(TOOLNAME).gif
-TARGET_TOOLBOX_FILES= $(TOOLBOX_FILES:%=$(EBIN)/%)
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-ERL_COMPILE_FLAGS +=
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-
-debug opt: $(TARGET_FILES)
-
-docs:
-
-clean:
- rm -f $(TARGET_FILES)
- rm -f core
-
-# ----------------------------------------------------
-# Special Build Targets
-# ----------------------------------------------------
-
-$(EBIN)/$(TOOLNAME).gif: $(TOOLNAME).gif
- $(gen_verbose)rm -f $@
- $(V_at)cp $(TOOLNAME).gif $@
-
-$(EBIN)/$(TOOLNAME).tool: $(TOOLNAME).tool
- $(gen_verbose)rm -f $@
- $(V_at)cp $(TOOLNAME).tool $@
-
-$(EBIN)/help.gif: help.gif
- $(gen_verbose)rm -f $@
- $(V_at)cp help.gif $@
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-release_spec: opt
- $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
- $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
- $(INSTALL_DIR) "$(RELSYSDIR)/mandel/bitmaps"
- $(INSTALL_DATA) $(BITMAPS) $(TOOLBOX_FILES) "$(RELSYSDIR)/mandel/bitmaps"
- $(INSTALL_DIR) "$(RELSYSDIR)/mandel"
- $(INSTALL_DATA) $(ERL_FILES) $(EXTRA_FILES) "$(RELSYSDIR)/mandel"
-
-release_docs_spec:
diff --git a/lib/gs/contribs/mandel/mandel.erl b/lib/gs/contribs/mandel/mandel.erl
deleted file mode 100644
index e6061ba77d..0000000000
--- a/lib/gs/contribs/mandel/mandel.erl
+++ /dev/null
@@ -1,351 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1996-2013. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-
--module(mandel).
--compile([{nowarn_deprecated_function,{gs,assq,2}},
- {nowarn_deprecated_function,{gs,config,2}},
- {nowarn_deprecated_function,{gs,create,4}},
- {nowarn_deprecated_function,{gs,image,2}},
- {nowarn_deprecated_function,{gs,start,0}}]).
--author('(mbj,eklas)@erlang.ericsson.se').
-
-%% User's interface
--export([start/0,start/1]).
-
-%% Internal exports:
--export([start_client/2,refresher/1,start_server/1,respond/2]).
-
-%%%-----------------------------------------------------------------
-%%% Distributed Mandelbrot program.
-%%% Originally written i C++/rpc/lwp/interviews by Klas Eriksson.(1200 lines)
-%%% Rewritten in Erlang by Klas Eriksson and Martin Björklund.
-%%%-----------------------------------------------------------------
-
-%% unix>erl -sname foo (all nodes will get the same name)
-%% (foo@data)1>mandel:start([{hosts,["computer1","computer2"]},{window,400}]).
-
-%% unix>erl
-%% 1> mandel:start().
-
--record(state,{image,width,height,xmax,ymax,range,
- maxiter,colortable,zoomstep}).
--record(job,{left,right,ymin,ymax,height,width,maxiter,data=[]}).
--define(JOBWIDTH,10).
-
-%%-----------------------------------------------------------------
-%% This is the client start function.
-%%-----------------------------------------------------------------
-start() ->
- start([]).
-
-%%----------------------------------------------------------------------
-%% Option is list of Option. Option is:
-%% {xmax,float()}|{ymax,float()}|{range,float()}|
-%% {maxiter,integer()}|{window,integer()}|{zoomstep,float()}|
-%% {hosts,(list of string())|all_found_nodes}
-%%----------------------------------------------------------------------
-start(Opts) ->
- Nodes1 = nodes(),
- Nodes = case get_option(hosts,Opts,all_found_nodes) of
- all_found_nodes when Nodes1 == [] ->
- N = [node()],
- spawn(mandel,start_server,[N]),
- N;
- all_found_nodes ->
- start_nodes(dir(),Nodes1),
- Nodes1;
- Hosts ->
- start_slaves(Hosts),
- start_nodes(dir(),Nodes1),
- Nodes1
- end,
- spawn(mandel,start_client,[Opts,Nodes]).
-
-%% This is not an application so we don't have their way of knowing
-%% a private data directory where the GIF files are located (this directory).
-%% We can find GS and makes it relative from there /kgb
-
--define(EbinFromGsPriv,"../contribs/ebin").
-
-dir()->
- GsPrivDir = code:priv_dir(gs),
- filename:join(GsPrivDir,?EbinFromGsPriv).
-
-
-start_slaves([]) -> ok;
-start_slaves([Host|Hs]) ->
- {ok,Name}=slave:start(Host),
- io:format("host ~p is up~n", [Name]),
- start_slaves(Hs).
-
-start_nodes(_Dir,[]) -> ok;
-start_nodes(Dir,[Node|Nodes]) ->
- rpc:call(Node,code,add_path,[Dir]), % hack? should be done in .erlang
- spawn_link(Node,mandel,start_server,[[node()]]),
- io:format("started mandelserver at node: ~p~n", [Node]),
- start_nodes(Dir,Nodes).
-
-start_client(Opts,Nodes) ->
- Wt = get_option(window,Opts,100) div ?JOBWIDTH * ?JOBWIDTH,
- Ht = get_option(window,Opts,100) div ?JOBWIDTH * ?JOBWIDTH,
- S=gs:start(),
- Win=gs:create(window,win1,S,[{title,"Mandel"},{width,Wt-1},{height,Ht-1},
- {configure,true}]),
- Canvas=gs:create(canvas,can1,Win,[{width,Wt},{height,Ht}]),
- Image=gs:image(Canvas,[{buttonpress,true}]),
- MaxIters = get_option(maxiter,Opts,100),
- timer:apply_after(8000,mandel,refresher,[Image]),
- CT = make_color_table(MaxIters),
- State2=#state{image=Image,width=Wt,height=Ht,
- xmax=try_random(get_option(xmax,Opts,2),-2,2),
- ymax=try_random(get_option(ymax,Opts,2),-2,2),
- range=try_random(get_option(range,Opts,4),0,4),
- maxiter=MaxIters,colortable=CT,
- zoomstep=get_option(zoomstep,Opts,1.7)},
- ToDo = make_jobs(State2),
- gs:config(Win,[{map,true}]),
- main(State2, [], Nodes, ToDo).
-
-try_random(random,Low,High) ->
- random:uniform()*(High-Low)+Low;
-try_random(Float,_Low,_High) when is_number(Float) -> Float.
-
-
-%%-----------------------------------------------------------------
-%% Distribute work to the nodes. When a node returns, that
-%% node is the first to be used if there's any job left.
-%%-----------------------------------------------------------------
-main(State, [], PassiveNodes, []) ->
- wait_event(State,[],PassiveNodes,[]);
-main(State, ActiveNodes, PassiveNodes, []) ->
- % No jobs left, but some nodes are still active.
- % Wait_Event for their results
- wait_event(State,ActiveNodes,PassiveNodes,[]);
-main(State, ActiveNodes, [Node|PassiveNodes], [Job|ToDo]) ->
- % We have work to do, and at least one passive node.
- % Let him do it.
- distribute_job(Node, Job),
- main(State, [Node|ActiveNodes], PassiveNodes, ToDo);
-main(State, ActiveNodes, [], ToDo) ->
- % We have work to do, but all nodes are active.
- _Node = wait_event(State,ActiveNodes,[],ToDo).
-
-wait_event(State,ActiveNodes,PassiveNodes,ToDo) ->
- receive
- {calculation_done, {Node, Job}} ->
- if % a small hack. we want to discard data for old pictures
- Job#job.ymax==State#state.ymax ->
- draw(State, Node, Job);
- true -> true
- end,
- main(State,lists:delete(Node,ActiveNodes),[Node|PassiveNodes],ToDo);
- {gs,_Img,buttonpress,_Data,[_Butt,X,Y|_]} ->
- #state{width=W,height=H,ymax=Ymax,xmax=Xmax,range=R,zoomstep=ZS} =
- State,
- RX = Xmax-R+(X/W)*R,
- RY = Ymax-R+(1-(Y/H))*R,
- R2 = R/ZS,
- Xmax2 = RX + R2/2,
- Ymax2 = RY + R2/2,
- State2 = State#state{xmax=Xmax2,ymax=Ymax2,range=R2},
- io:format("{xmax,~w},{ymax,~w},{range,~w}~n", [Xmax2,Ymax2,R2]),
- ToDo2=make_jobs(State2),
- main(State2,ActiveNodes,PassiveNodes,ToDo2);
- {gs,_Win,destroy,_,_} ->
- kill_nodes(lists:append(ActiveNodes,PassiveNodes));
- {gs,_Win,configure,_Data,[W,H|_]}
- when State#state.width==W+1, State#state.height==H+1->
- main(State,ActiveNodes,PassiveNodes,ToDo);
- {gs,_Win,configure,_Data,[W|_]} ->
- gs:config(can1,[{width,W},{height,W}]),
- gs:config(win1,{configure,false}),
- gs:config(win1,[{width,W-1},{height,W-1}]),
- gs:config(win1,{configure,true}),
- State2 = State#state{width=W,height=W},
- ToDo2=make_jobs(State2),
- main(State2,ActiveNodes,PassiveNodes,ToDo2)
- end.
-
-kill_nodes([]) ->
- done;
-kill_nodes([Node|Nodes]) ->
- exit(rpc:call(Node,erlang,whereis,[mandel_server]),kill),
- kill_nodes(Nodes).
-
-
-distribute_job(Node, Job) ->
- {mandel_server, Node} ! {mandel_job, {self(), Job}}.
-
-draw(#state{image=Image, width=Wt, height=Ht, xmax=Xmax,
- maxiter=MI,colortable=ColorTable,range=R}, Node, Job) ->
- #job{left=Left,data=Data}=Job,
- io:format("Got data from node ~30w~n", [Node]),
-%% PixelX = K * RealX + M
-%% 0 = K * Xmin + M
-%% Width-1= K * Xmax + M
- K=(1-Wt)/-R,
- M=Wt-1-K*Xmax,
- Xbegin = round(Left*K+M),
- draw_cols(Image, Xbegin, Ht, lists:reverse(Data),MI,ColorTable).
-
-draw_cols(Image, X, Ht, [H|T],MaxIter,ColorTable) ->
- draw_col(Image, X, 0, H,MaxIter,ColorTable),
- draw_cols(Image, X+1, Ht, T,MaxIter,ColorTable);
-draw_cols(_Image, _X, _, [],_MaxIter,_ColorTable) ->
- done.
-
-draw_col(_Image, _X,_Y,[{no_first_color,0}],_MaxIter,_ColorTable) ->
- done;
-draw_col(Image, X,Y,[{Color,1}|T],MaxIter,ColorTable) ->
- gs:config(Image,[{pix_val,{{X,Y},
- element(Color+1,ColorTable)}}]),
- draw_col(Image, X,Y+1,T,MaxIter,ColorTable);
-draw_col(Image, X,Y,[{Color,Height}|T],MaxIter,ColorTable) ->
- gs:config(Image,[{pix_val,{{{X,Y},{X+1,Y+Height}},
- element(Color+1,ColorTable)}}]),
- draw_col(Image, X,Y+Height,T,MaxIter,ColorTable).
-
-make_jobs(#state{width=W,height=H,range=R,
- xmax=Xmax,ymax=Ymax,maxiter=MI}) ->
- make_jobs(Xmax-R,Xmax,Ymax-R,Ymax,H,W,MI).
-
-make_jobs(Xmin,Xmax,Ymin,Ymax,Ht,Wt,MaxIter) ->
- NoJobs = Wt/?JOBWIDTH, % Each job is ?JOBWIDTH pixel-col
- DX = (Xmax - Xmin)/NoJobs,
- make_jobs(DX,Xmin,Xmax,#job{ymin=Ymin,ymax=Ymax,height=Ht,width=Wt/NoJobs,
- maxiter=MaxIter},[]).
-
-make_jobs(DX,Left,Xmax,JobSkel,Res) when Left =< Xmax ->
- Right = Left + DX,
- Job = JobSkel#job{left=Left,right=Right},
- make_jobs(DX,Right,Xmax,JobSkel,[Job | Res]);
-make_jobs(_DX,_Left,_Xmax,_JobSkel,Res) -> Res.
-
-%%----------------------------------------------------------------------
-%% A small process that refreshes the screen now and then.
-%%----------------------------------------------------------------------
-refresher(Image) ->
- gs:config(Image,flush),
- timer:apply_after(8000,mandel,refresher,[Image]).
-
-%%-----------------------------------------------------------------
-%% This is the server start function.
-%%-----------------------------------------------------------------
-start_server([ClientNode]) ->
- register(mandel_server, self()),
- erlang:monitor_node(ClientNode, true),
- server_loop().
-
-server_loop() ->
- receive
- {mandel_job, {Pid, Job}} ->
- spawn_link(mandel, respond, [Pid, Job]),
- server_loop()
- end.
-
-respond(Pid, Job) ->
- Data = do_job(Job),
- Pid ! {calculation_done, {node(), Data}}.
-
-do_job(Job) ->
- calculate_area(Job).
-
-calculate_area(Job) ->
- #job{ymin=Ymin,ymax=Ymax,height=Ht,width=Wt,left=Xmin,right=Xmax}=Job,
- Job#job{data=x_loop(0,[],Wt,(Xmax-Xmin)/Wt,(Ymax-Ymin)/Ht,Xmin,Job)}.
-
-x_loop(IX,Res,Wt,Dx,Dy,X,Job) when IX < Wt ->
- #job{ymin=Ymin,height=Ht,maxiter=MaxIter}=Job,
- Cols = y_loop(0,Ht,[],MaxIter,Dy,X,Ymin,no_first_color,0),
- x_loop(IX+1,[Cols|Res],Wt,Dx,Dy,X+Dx,Job);
-x_loop(_,Res,_,_,_,_,_) ->
- Res.
-
-y_loop(IY,Ht,Res,MaxIter,Dy,X,Y,PrevColor,NprevColor) when IY < Ht ->
- Color = color_loop(1,MaxIter,0,0,0,0,X,Y),
- if
- Color == PrevColor ->
- y_loop(IY+1,Ht,Res,MaxIter,Dy,X,Y+Dy,PrevColor,NprevColor+1);
- true ->
- y_loop(IY+1,Ht,[{PrevColor,NprevColor}|Res],MaxIter,
- Dy,X,Y+Dy,Color,1)
- end;
-
-y_loop(_,_,Res,_,_,_,_,PC,N) ->
- [{PC,N}|Res].
-
-color_loop(Color,MaxIter,Za,Zb,Za2,Zb2,X,Y)
- when Za2 + Zb2 < 4, Color < MaxIter->
- Ztmp = Za2 - Zb2 + X,
- ZbN = 2 * Za * Zb + Y,
- color_loop(Color+1,MaxIter,Ztmp,ZbN,Ztmp * Ztmp,ZbN * ZbN,X,Y);
-color_loop(MaxIter,MaxIter,_Za,_Zb,_Za2,_Zb2,_X,_Y) ->
- 0; % black
-color_loop(Color,_,_,_,_,_,_,_) ->
- Color.
-
-%%----------------------------------------------------------------------
-%% The "colormodel".
-%%----------------------------------------------------------------------
-make_color_table(MaxColors) ->
- list_to_tuple([{0,0,0}|colors(MaxColors)]).
-
-colors(Ncolors) ->
- {A,B,C}=erlang:now(),
- random:seed(A,B,C),
- Colors = random_colors(Ncolors),
- Colors2 = best_insert([hd(Colors)],tl(Colors)),
- Colors2.
-
-random_colors(0) -> [];
-random_colors(N) ->
- R = random:uniform(256)-1,
- G = random:uniform(256)-1,
- B = random:uniform(256)-1,
- [{R,G,B}|random_colors(N-1)].
-
-best_insert(Sorted,[RGB|Unsorted]) ->
- best_insert(insert_at(best_pos(RGB,Sorted),RGB,Sorted),Unsorted);
-best_insert(Sorted,[]) -> Sorted.
-
-insert_at(1,Elem,L) -> [Elem|L];
-insert_at(N,Elem,[H|T]) -> [H|insert_at(N-1,Elem,T)].
-
-best_pos(RGB, Sorted) ->
- D = distances(RGB,Sorted),
- pos_for_smallest_distance(D,1,1000,-1).
-
-pos_for_smallest_distance([],_CurPos,_SmallestDist,Pos) -> Pos;
-pos_for_smallest_distance([Dist|T],CurPos,SmallDist,_Pos)
- when Dist < SmallDist ->
- pos_for_smallest_distance(T,CurPos+1,Dist,CurPos);
-pos_for_smallest_distance([_|T],CurPos,Smallest,Pos) ->
- pos_for_smallest_distance(T,CurPos+1,Smallest,Pos).
-
-distances(_RGB,[]) ->
- [];
-distances({R,G,B},[{R2,G2,B2}|T]) ->
- [lists:max([abs(R-R2),abs(G-G2),abs(B-B2)])|distances({R,G,B},T)].
-
-get_option(Option, Options, Default) ->
- case gs:assq(Option, Options) of
- {value, Val} -> Val;
- false -> Default
- end.
diff --git a/lib/gs/contribs/mandel/mandel.gif b/lib/gs/contribs/mandel/mandel.gif
deleted file mode 100644
index 49ed1985cb..0000000000
--- a/lib/gs/contribs/mandel/mandel.gif
+++ /dev/null
Binary files differ
diff --git a/lib/gs/contribs/mandel/mandel.html b/lib/gs/contribs/mandel/mandel.html
deleted file mode 100644
index f69cfa3c6a..0000000000
--- a/lib/gs/contribs/mandel/mandel.html
+++ /dev/null
@@ -1,74 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
-<!--
- ``Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson Utvecklings AB.
- Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
- AB. All Rights Reserved.''
-
- $Id$
--->
-<HTML>
-<HEAD>
- <TITLE></TITLE>
- <META NAME="GENERATOR" CONTENT="Mozilla/3.01Gold (X11; I; SunOS 5.5.1 sun4m) [Netscape]">
-</HEAD>
-<BODY>
-
-<H1>Distributed Mandelbrot program</H1>
-
-<P>Originally written i C++/rpc/lwp/interviews by Klas Eriksson.(1200 lines)
-<BR>
-Rewritten in Erlang by Klas Eriksson and Martin Bj&ouml;rklund. </P>
-
-<P><A HREF="http://www.bush.edu/~nick/nick.html">What is the Mandelbrot
-function?</A> </P>
-
-<H2>A small manual</H2>
-
-<UL>
-<LI>Try starting erlang in distributed mode. The mandel program will use<BR>
-all connected nodes for mandel calculations!</LI>
-
-<LI>Resizing the window will restart the calculation.</LI>
-
-<LI>Press left mouse button to zoom.</LI>
-</UL>
-
-<P><TT>mandel:start(list of Option)</TT> can be used to give the program
-different options.</P>
-
-<P><BR>
-Available options are:</P>
-
-<UL>
-<LI>{xmax,float()}</LI>
-
-<LI>{ymax,float()}</LI>
-
-<LI>{range,float()}|</LI>
-
-<LI>{maxiter,integer()}</LI>
-
-<LI>{window,integer()}</LI>
-
-<LI>{zoomstep,float()}</LI>
-
-<LI>{hosts,(list of string())|all_found_nodes}</LI>
-</UL>
-
-<P><BR>
-</P>
-
-</BODY>
-</HTML>
diff --git a/lib/gs/contribs/mandel/mandel.tool b/lib/gs/contribs/mandel/mandel.tool
deleted file mode 100644
index b59941268e..0000000000
--- a/lib/gs/contribs/mandel/mandel.tool
+++ /dev/null
@@ -1,6 +0,0 @@
-{version,"0.1"}.
-{{tool,"Mandel"},
- {start,{mandel,start,[]}},
- {icon,"mandel.gif"},
- {message,"Mandelbrot"},
- {html,"../mandel/mandel.html"}}.
diff --git a/lib/gs/contribs/othello/Makefile b/lib/gs/contribs/othello/Makefile
deleted file mode 100644
index 8a66e17ec5..0000000000
--- a/lib/gs/contribs/othello/Makefile
+++ /dev/null
@@ -1,101 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1996-2012. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-
-#
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../../vsn.mk
-VSN=$(GS_VSN)
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/gs-$(VSN)/contribs
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-
-MODULES= \
- othello \
- othello_adt \
- othello_board
-
-HRL_FILES=
-
-ERL_FILES= $(MODULES:%=%.erl)
-
-TARGET_FILES= $(MODULES:%=../ebin/%.$(EMULATOR)) $(TARGET_TOOLBOX_FILES)
-
-TOOLNAME = othello
-
-EXTRA_FILES=
-TOOLBOX_FILES= $(TOOLNAME).tool $(TOOLNAME).gif
-TARGET_TOOLBOX_FILES= $(TOOLBOX_FILES:%=$(EBIN)/%)
-BITMAPS= priv/marker.bm priv/square.bm
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-ERL_COMPILE_FLAGS +=
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-
-debug opt: $(TARGET_FILES)
-
-docs:
-
-clean:
- rm -f $(TARGET_FILES)
- rm -f core
-
-# ----------------------------------------------------
-# Special Build Targets
-# ----------------------------------------------------
-
-$(EBIN)/$(TOOLNAME).gif: $(TOOLNAME).gif
- $(gen_verbose)rm -f $@
- $(V_at)cp $(TOOLNAME).gif $@
-
-$(EBIN)/$(TOOLNAME).tool: $(TOOLNAME).tool
- $(gen_verbose)rm -f $@
- $(V_at)cp $(TOOLNAME).tool $@
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-release_spec: opt
- $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
- $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
- $(INSTALL_DIR) "$(RELSYSDIR)/othello"
- $(INSTALL_DATA) $(ERL_FILES) $(EXTRA_FILES) "$(RELSYSDIR)/othello"
- $(INSTALL_DIR) "$(RELSYSDIR)/othello/priv"
- $(INSTALL_DATA) $(BITMAPS) $(TOOLBOX_FILES) "$(RELSYSDIR)/othello/priv"
-
-release_docs_spec:
-
diff --git a/lib/gs/contribs/othello/othello.erl b/lib/gs/contribs/othello/othello.erl
deleted file mode 100644
index c6ad0a76ec..0000000000
--- a/lib/gs/contribs/othello/othello.erl
+++ /dev/null
@@ -1,237 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%
--module(othello).
--export([start/0,new_game/4,start1/5]).
-
-
-
-%%----------------------------------------------------------------------
-%% The Othello program now uses the gs graphical package instead of the
-%% pxw package. See module othello_board for details
-%%
-%%----------------------------------------------------------------------
-
-
-start() -> othello_board:start().
-
-new_game(Computer,Player,Depth,Init) ->
- spawn_link(othello,start1,[self(),Computer,Player,Depth,Init]).
-
-start1(Win,Computer,Player,Depth,Init) ->
- Board = othello_adt:new(t),
- random:seed(),
- init_display(Board,Win,Init),
- play(Computer,Player,Board,Depth,Win,1).
-
-play(Computer,Player,Board,Depth,Win,NoDs) ->
- tell_win(Win,Computer,Player),
- case catch continue(Player,Board) of
- {game_over,Result} ->
- game_over(Board,Player,Result,Win);
- {omit_draw,Player} ->
- omit(Player,Win),
- play(Computer,swap(Player),Board,Depth,Win,NoDs);
- ok ->
- Draw = choose_draw(Computer,Player,Board,Depth,Win,NoDs),
- Win ! {self(),draw,Draw},
- Board1 = othello_adt:set(Draw,Player,Board),
- display(Board1,Board,Win),
- play(Computer,swap(Player),Board1,Depth,Win,NoDs+1)
- end.
-
-continue(Player,Board) ->
- Draws = game_over(Player,Board),
- not_allowed(Draws,Player),
- ok.
-
-choose_draw(Computer,Computer,Board,Depth,_Win,NoDs) -> % Depth > 0 !!
- {Draw,_Value} = alpha_beta(Depth,Board,-11000,11000,Computer,NoDs),
-% io:format('Choosen draw is {~w,~w} : (~w)~n',
-% [othello_adt:col(Draw),othello_adt:row(Draw),Value]),
-% io:format('=====================~n',[]),
- Draw;
-choose_draw(Computer,Player,Board,Depth,Win,NoDs) ->
- receive
- {Win,position,Draw} ->
- flush(Win),
- case othello_adt:is_draw(Draw,Player,Board) of
- false ->
- Win ! {self(),illegal_draw,Draw},
- choose_draw(Computer,Player,Board,Depth,Win,NoDs);
- true ->
- Draw
- end
- end.
-
-flush(Win) ->
- receive
- {Win,position,_} ->
- flush(Win)
- after 1 ->
- true
- end.
-
-tell_win(Win,Computer,Player) ->
- Win ! {self(),player,Computer,Player},
- receive
- {Win,go_on_play} -> true
- end.
-
-alpha_beta(0,Board,_,_,Player,_) ->
- {-1,othello_adt:evaluate_board(Player,Board)};
-alpha_beta(Depth,Board,Alpha,Beta,Player,NoDs) ->
- case compute(Player,Board,NoDs) of
- [] ->
- Player1 = swap(Player),
- case compute(Player1,Board,NoDs) of
- [] ->
- dead_lock(Board,Player);
- PosDraws1 ->
- choose(PosDraws1,Board,Depth-1,-Beta,-Alpha,-1,
- Player1,NoDs)
- end;
- PosDraws ->
- choose(PosDraws,Board,Depth-1,-Beta,-Alpha,-1,Player,NoDs)
-% A = choose(PosDraws,Board,Depth-1,-Beta,-Alpha,-1,Player,NoDs),
-% io:format('Alpha-Beta (~w) ==> ~w~n',[Depth,A]),
-% A
- end.
-
-choose([Draw|Draws],Board,Depth,Alpha,Beta,Record,Player,NoDs) ->
- Player1 = swap(Player),
- Board1 = othello_adt:set(Draw,Player,Board),
-% io:format('Alpha <~w> Beta <~w> ~n',[Alpha,Beta]),
- {_,Value} = alpha_beta(Depth,Board1,Alpha,Beta,Player1,NoDs+1),
- Value1 = -Value,
- cutoff(Draw,Value1,Depth,Alpha,Beta,Draws,Board,Record,Player,NoDs);
-choose([],_,_,Alpha,_,Draw,_,_) ->
- {Draw,Alpha}.
-
-cutoff(Draw,Value,_,_,Beta,_,_,_,_,_) when Value >= Beta ->
- {Draw,Value};
-cutoff(Draw,Value,Depth,Alpha,Beta,Draws,Board,_,Player,NoDs)
- when Alpha < Value, Value < Beta ->
- choose(Draws,Board,Depth,Value,Beta,Draw,Player,NoDs);
-cutoff(Draw,Value,Depth,Alpha,Beta,Draws,Board,Record,Player,NoDs)
- when Value == Alpha, NoDs < 13 ->
- choose(Draws,Board,Depth,Alpha,Beta,random_choice(Draw,Record),
- Player,NoDs);
-cutoff(_Draw,Value,Depth,Alpha,Beta,Draws,Board,Record,Player,NoDs)
- when Value =< Alpha ->
- choose(Draws,Board,Depth,Alpha,Beta,Record,Player,NoDs).
-
-compute(Player,Board,NoOfDraws) when NoOfDraws < 13 ->
- case othello_adt:possible_draws(Player,Board,begin_play) of
- [] ->
- othello_adt:possible_draws(Player,Board,playing);
- Draws ->
- Draws
- end;
-compute(Player,Board,_) ->
- othello_adt:possible_draws(Player,Board,playing).
-
-%%----------------------------------------------------------
-%% Randomly choose between two draws with the same value.
-%%----------------------------------------------------------
-
-random_choice(Draw,Draw1) ->
- case random:uniform(2) of
- 1 ->
- Draw;
- 2 ->
- Draw1
- end.
-
-dead_lock(Board,Player) ->
- case win_or_loose(Board,Player) of
- 0 -> {-1,0};
- Value when Value > 0 -> {-1,10000};
- _ -> {-1,-10000}
- end.
-
-win_or_loose(Board,Player) ->
- Player1 = swap(Player),
- othello_adt:pieces(Player,Board) - othello_adt:pieces(Player1,Board).
-
-game_over(Player,Board) ->
- case othello_adt:possible_draws(Player,Board,playing) of
- [] ->
- Player1 = swap(Player),
- case othello_adt:possible_draws(Player1,Board,playing) of
- [] ->
- throw({game_over,{{Player,othello_adt:pieces(Player,Board)},
- {Player1,othello_adt:pieces(Player1,Board)}}});
- _ ->
- [] % Player`s Draws !!
- end;
- Draws ->
- Draws
- end.
-
-game_over(_Board,_Player,Result,Win) ->
- Win ! {self(),game_over,white_res(Result),black_res(Result)}.
-
-white_res({{white,Res},_}) -> Res;
-white_res({_,{white,Res}}) -> Res.
-
-black_res({{black,Res},_}) -> Res;
-black_res({_,{black,Res}}) -> Res.
-
-not_allowed([],Player) ->
- throw({omit_draw, Player});
-not_allowed(_,_Player) ->
- ok.
-
-omit(Player,Win) ->
- Win ! {self(),omit_draw,Player},
- receive
- {Win,continue} ->
- ok
- end.
-
-init_display(_Board,_Win,first_time) ->
- true;
-init_display(Board,Win,_) ->
- display(Board,Win).
-
-display(Board,Win) ->
- All = othello_adt:all_pos(Board),
- display1(All,Win),
- Win ! {self(),score,othello_adt:pieces(white,Board),
- othello_adt:pieces(black,Board)}.
-
-display(Board,OldB,Win) ->
- Diff = othello_adt:diff(Board,OldB),
- display1(Diff,Win),
- Win ! {self(),score,othello_adt:pieces(white,Board),
- othello_adt:pieces(black,Board)}.
-
-display1([{Pos,Colour}|Diff],Win) ->
- Win ! {self(),new_mark,Pos,Colour},
- display1(Diff,Win);
-display1(_,_) ->
- true.
-
-swap(white) -> black;
-swap(black) -> white.
-
-
diff --git a/lib/gs/contribs/othello/othello.gif b/lib/gs/contribs/othello/othello.gif
deleted file mode 100644
index 5970c50209..0000000000
--- a/lib/gs/contribs/othello/othello.gif
+++ /dev/null
Binary files differ
diff --git a/lib/gs/contribs/othello/othello.tool b/lib/gs/contribs/othello/othello.tool
deleted file mode 100644
index 47550a581d..0000000000
--- a/lib/gs/contribs/othello/othello.tool
+++ /dev/null
@@ -1,6 +0,0 @@
-{version,"0.1"}.
-{{tool,"Othello"},
- {start,{othello,start,[]}},
- {icon,"othello.gif"},
- {message,"Othello - The Game"},
- {html,"http://www.armory.com/~iioa/othguide.html"}}.
diff --git a/lib/gs/contribs/othello/othello_adt.erl b/lib/gs/contribs/othello/othello_adt.erl
deleted file mode 100644
index e69c1c4d72..0000000000
--- a/lib/gs/contribs/othello/othello_adt.erl
+++ /dev/null
@@ -1,540 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%
--module(othello_adt).
--compile(export_all).
-%%-------------------------------------------------------
-%% Use three main states for the strategy:
-%%
-%% BeginPlay: Stay in the inner square as long as possible.
-%% Use the possible_draws/3.
-%%
-%% MiddlePlay: Try to choose stable markers (?)
-%% Use stable/3
-%%
-%% EndPlay: Try to flip as many markers as possible
-%%
-%% The transition from Begin to Middle is obvious. From Middle
-%% to End however, is can be discussed.
-%%-------------------------------------------------------
-
-test(N,B) ->
- X=new(B),
- statistics(wall_clock),
- test0(N,X),
- {_,T} = statistics(wall_clock),
- {time_was,T/N}.
-
-
-test0(0,_) -> true;
-test0(N,X) ->
- possible_draws(black,X,begin_play),
- test0(N-1,X).
-
-%%-------------------------------------------------------
-%% new/1 - returns a new board
-%%
-%% Uses a tuple for storing the board
-%%-------------------------------------------------------
-
-new(B) ->
- Board = mk_board(B),
- {ordsets:from_list([18,19,20,21,26,29,34,37,42,43,44,45]),Board}.
-
-mk_board(t) ->
- Tup = list_to_tuple(gen_list(64,grey)),
- Tup1 = setelement(28+1, Tup, white),
- Tup2 = setelement(35+1, Tup1, white),
- Tup3 = setelement(27+1, Tup2, black),
- gen_score_board(),
- setelement(36+1, Tup3, black).
-
-gen_list(0,_) -> [];
-gen_list(I,Def) -> [Def|gen_list(I-1,Def)].
-
-gen_score_board() -> put(score,list_to_tuple(gen_list(64,0))).
-
-%%-------------------------------------------------------
-%% pos(Col,Row) - returns a position describing column
-%% and row.
-%% Col and Row have the range 1 - 8.
-%%-------------------------------------------------------
-
-pos(Col,Row) -> ((Row - 1) bsl 3) + (Col - 1).
-
-%%-------------------------------------------------------
-%% col(Pos) - returns the column of the Pos position
-%%-------------------------------------------------------
-
-col(Pos) -> (Pos band 7) + 1.
-
-%%-------------------------------------------------------
-%% row(Pos) - returns the row of the Pos position
-%%-------------------------------------------------------
-
-row(Pos) -> (Pos bsr 3) + 1.
-
-%%-------------------------------------------------------
-%% is_draw(Pos,Colour,Board) - returns true if Pos is a
-%% correct draw.
-%%-------------------------------------------------------
-
-is_draw(Pos,Colour,{Bset,Board}) ->
- case ordsets:is_element(Pos,Bset) of
- true ->
- case catch is_good(Colour,Pos,Board) of
- true ->
- true;
- _ ->
- false
- end;
- _ ->
- false
- end.
-
-%%-------------------------------------------------------
-%% set(Pos,Colour,Board) - returns an updated board
-%%-------------------------------------------------------
-
-set(Pos,Colour,{Bset,Board}) ->
- case ordsets:is_element(Pos,Bset) of
- true ->
- NewBoard = setelement(Pos+1,Board,Colour),
- Empty = empty_neighbour(Pos,NewBoard),
- NewBset = ordsets:union(Empty,ordsets:del_element(Pos,Bset)),
- turn(Colour,Pos,{NewBset,NewBoard});
- _ ->
- {error,invalid_position}
- end.
-
-empty_neighbour(Pos,Board) ->
- ordsets:from_list(empty_neighbour(Pos,Board,deltas())).
-
-empty_neighbour(_,_,[]) -> [];
-empty_neighbour(Pos,Board,[H|T]) ->
- case is_empty(Pos+H,dir(Pos,H),Board) of
- true -> [Pos+H|empty_neighbour(Pos,Board,T)];
- _ -> empty_neighbour(Pos,Board,T)
- end.
-
-is_empty(_,false,_) -> false;
-is_empty(X,_,_Board) when X<0 -> false;
-is_empty(X,_,_Board) when X>63 -> false;
-is_empty(X,_,Board) ->
- case element(X+1,Board) of
- grey -> true; % Empty
- _ -> false
- end.
-
-%%-------------------------------------------------------
-%% get(Pos,Board) - returns the contents in Pos
-%%-------------------------------------------------------
-
-get(Pos,{_Bset,Board}) -> element(Pos+1,Board).
-
-%%-------------------------------------------------------
-%% pieces(Colour,Board) - returns the number of Colour
-%% pieces.
-%%-------------------------------------------------------
-
-pieces(Colour,{_Bset,Board}) ->
- pieces(Colour,Board,0,0).
-
-pieces(Colour,Board,Pos,Count) when Pos < 64 ->
- case element(Pos+1,Board) of
- Colour ->
- pieces(Colour,Board,Pos+1,Count+1);
- _ ->
- pieces(Colour,Board,Pos+1,Count)
- end;
-pieces(_,_,_,Count) ->
- Count.
-
-%%-------------------------------------------------------
-%% possible_draws(Colour, Board, State)
-%%
-%% Returns a list of possible draws regarding the current
-%% strategy state.
-%%-------------------------------------------------------
-
-possible_draws(Colour,{Bset,Board},begin_play) ->
- Dset = ordsets:intersection(Bset,inner_square()),
- possible_draws_0(Colour,Dset,Board);
-possible_draws(Colour,{Bset,Board},_) ->
- possible_draws_0(Colour,Bset,Board).
-
-possible_draws(Colour,{Bset,Board}) ->
- possible_draws_0(Colour,Bset,Board).
-
-possible_draws_0(_,[],_) -> [];
-possible_draws_0(Colour,[H|T],Board) ->
- case catch is_good(Colour,H,Board) of
- true -> [H|possible_draws_0(Colour,T,Board)];
- false -> possible_draws_0(Colour,T,Board)
- end.
-
-
-%%-------------------------------------------------------
-%% evaluate_board(Colour,Board) - returns the value of
-%% the board from Colours
-%% point of view.
-%%-------------------------------------------------------
-
-evaluate_board(Colour,{_Bset,Board}) ->
- Score = get(score), % Initialized (zeroed) score board !!
- Colour1 = swap(Colour),
- Score1 = eval_board(Colour,Colour1,Score,Board,0),
- Score2 = cnt_corner(0,Score1,Board,Colour,Colour1),
- Score3 = cnt_corner(7,Score2,Board,Colour,Colour1),
- Score4 = cnt_corner(56,Score3,Board,Colour,Colour1),
- Score5 = cnt_corner(63,Score4,Board,Colour,Colour1),
- count(Score5,0).
-% A = count(Score5,0),
-% io:format('Score = ~w~n',[A]),
-% A.
-
-eval_board(MyCol,OtCol,Score,Board,Pos) when Pos < 64 ->
- case element(Pos+1,Board) of
- MyCol ->
- Score1 = setelement(Pos+1,Score,score(Pos)),
- eval_board(MyCol,OtCol,Score1,Board,Pos+1);
- OtCol ->
- Score1 = setelement(Pos+1,Score,-score(Pos)),
- eval_board(MyCol,OtCol,Score1,Board,Pos+1);
- _ ->
- eval_board(MyCol,OtCol,Score,Board,Pos+1)
- end;
-eval_board(_,_,Score,_,_) ->
- Score.
-
-cnt_corner(Corner,Score,Board,MyCol,OtCol) ->
- case element(Corner+1,Board) of
- MyCol ->
- cnt_corn(Corner,setelement(Corner+1,Score,50),
- Board,50,MyCol);
- OtCol ->
- cnt_corn(Corner,setelement(Corner+1,Score,-50),
- Board,-50,OtCol);
- _ ->
- Score
- end.
-
-cnt_corn(0,Score,Board,Value,Colour) ->
- Score1 = cnt_corn(0,1,8,Score,Board,Value,Colour),
- cnt_corn(0,8,1,Score1,Board,Value,Colour);
-cnt_corn(7,Score,Board,Value,Colour) ->
- Score1 = cnt_corn(7,-1,8,Score,Board,Value,Colour),
- cnt_corn(7,8,-1,Score1,Board,Value,Colour);
-cnt_corn(56,Score,Board,Value,Colour) ->
- Score1 = cnt_corn(56,1,-8,Score,Board,Value,Colour),
- cnt_corn(56,-8,1,Score1,Board,Value,Colour);
-cnt_corn(63,Score,Board,Value,Colour) ->
- Score1 = cnt_corn(63,-1,-8,Score,Board,Value,Colour),
- cnt_corn(63,-8,-1,Score1,Board,Value,Colour).
-
-cnt_corn(Pos,Dir,LineDir,Score,Board,Value,Colour) ->
- case dir(Pos,Dir) of
- Dir ->
- NextEdge = Pos+Dir,
- case element(NextEdge+1,Board) of
- Colour ->
- Score1 = setelement(NextEdge+1,Score,Value),
- Score2 = cnt_line(NextEdge,LineDir,Score1,Board,
- Colour,Value),
- cnt_corn(NextEdge,Dir,LineDir,Score2,Board,Value,Colour);
- _ ->
- Score
- end;
- _ ->
- Score
- end.
-
-cnt_line(Pos,Dir,Score,Board,Colour,Value) ->
- case dir(Pos,Dir) of
- Dir ->
- OnLinePos = Pos+Dir,
- case element(OnLinePos+1,Board) of
- Colour ->
- Score1 = setelement(OnLinePos+1,Score,Value),
- cnt_line(OnLinePos,Dir,Score1,Board,Colour,Value);
- _ ->
- Score
- end;
- _ ->
- Score
- end.
-
-count(Score,Pos) when Pos < 64 ->
- element(Pos+1,Score) + count(Score,Pos+1);
-count(_,_) ->
- 0.
-
-swap(white) -> black;
-swap(black) -> white.
-
-%%-------------------------------------------------------
-%% stable(Colour,Pos,Board) - returns a value 0-8
-%%
-%% A high value is regarded as more stable than a lower one.
-%% The stability means how many "friendly" neighbours there
-%% are, i.e markers of the same colour. Neighbours positions
-%% outside the board are regarded as friendly.
-%%-------------------------------------------------------
-
-stable(Colour,Pos,{_,Board}) ->
- stable(deltas(),Colour,Pos,Board).
-
-stable([],_,_,_) -> 0;
-stable([H|T],Colour,Pos,Board) ->
- stable_val(Colour,Pos,H,Board) + stable(T,Colour,Pos,Board).
-
-stable_val(_,H,D,_) when H+D<0 -> 1;
-stable_val(_,H,D,_) when H+D>63 -> 1;
-stable_val(black,H,D,Board) ->
- case element((H+D)+1,Board) of
- black -> 1;
- _ -> 0
- end;
-stable_val(white,H,D,Board) ->
- case element((H+D)+1,Board) of
- white -> 1;
- _ -> 0
- end.
-
-%%-------------------------------------------------------
-%% diff(Board,OldBoard) - return a list of the positions
-%% with changed pieces.
-%% [{Pos1,Colour1},...]
-%%-------------------------------------------------------
-
-diff(Board,OldBoard) -> diff(0,Board,OldBoard).
-
-diff(Pos,Board,OldBoard) when Pos < 64 ->
- OldP = get(Pos,OldBoard),
- case get(Pos,Board) of
- OldP ->
- diff(Pos+1,Board,OldBoard);
- NewP ->
- [{Pos,NewP}|diff(Pos+1,Board,OldBoard)]
- end;
-diff(_,_,_) ->
- [].
-
-%%-------------------------------------------------------
-%% all_pos(Board) - return a list of the positions colour.
-%% [{Pos1,Colour1},...]
-%%-------------------------------------------------------
-
-all_pos(Board) -> all_pos(0,Board).
-
-all_pos(Pos,Board) when Pos < 64 ->
- [{Pos,get(Pos,Board)}|all_pos(Pos+1,Board)];
-all_pos(_,_) ->
- [].
-
-%%-------------------------------------------------------
-%% Internal stuff
-%%-------------------------------------------------------
-
-deltas() -> [9,8,7,1,-1,-7,-8,-9].
-
-inner_square() ->
- [18,19,20,21,26,27,28,29,34,35,36,37,42,43,44,45]. % Is already an ordset
- % Save list traversing.
-% ordsets:list_to_set([18,19,20,21,26,27,28,29,34,35,36,37,42,43,44,45]).
-
-inv(black) -> white;
-inv(white) -> black.
-
-is_good(Colour,H,Board) ->
- is_good_0(Colour,H,dir(H,-9),Board),
- is_good_0(Colour,H,dir(H,-8),Board),
- is_good_0(Colour,H,dir(H,-7),Board),
- is_good_0(Colour,H,dir(H,-1),Board),
- is_good_0(Colour,H,dir(H,1),Board),
- is_good_0(Colour,H,dir(H,7),Board),
- is_good_0(Colour,H,dir(H,8),Board),
- is_good_0(Colour,H,dir(H,9),Board),
- false.
-
-is_good_0(_,_,false,_) -> false;
-is_good_0(_,H,D,_) when is_integer(H), is_integer(D), H+D<0 -> false;
-is_good_0(_,H,D,_) when is_integer(H), is_integer(D), H+D>63 -> false;
-is_good_0(black,H,D,Board) when is_integer(H), is_integer(D) ->
- case element((H+D)+1,Board) of
- white -> is_good_1(black,H+D,dir(H+D,D),Board);
- _ -> false
- end;
-is_good_0(white,H,D,Board) when is_integer(H), is_integer(D) ->
- case element((H+D)+1,Board) of
- black -> is_good_1(white,H+D,dir(H+D,D),Board);
- _ -> false
- end.
-
-is_good_1(_,_,false,_) -> false;
-is_good_1(_,H,D,_) when is_integer(H), is_integer(D), H+D<0 -> false;
-is_good_1(_,H,D,_) when is_integer(H), is_integer(D), H+D>63 -> false;
-is_good_1(black,H,D,Board) when is_integer(H), is_integer(D) ->
- case element((H+D)+1,Board) of
- white -> is_good_1(black,H+D,dir(H+D,D),Board);
- black -> throw(true);
- _ -> false
- end;
-is_good_1(white,H,D,Board) when is_integer(H), is_integer(D) ->
- case element((H+D)+1,Board) of
- black -> is_good_1(white,H+D,dir(H+D,D),Board);
- white -> throw(true);
- _ -> false
- end.
-
-%%-------------------------------------------------------
-%% turn(Colour,Draw,Board) - returns an updated board
-%% turn all possible pieces
-%% on the board
-%% Neighbours are not changed !!
-%%-------------------------------------------------------
-
-turn(Colour,Draw,{Bset,Board}) ->
- {Bset,turn(Colour,Draw,-9,
- turn(Colour,Draw,-8,
- turn(Colour,Draw,-7,
- turn(Colour,Draw,-1,
- turn(Colour,Draw,1,
- turn(Colour,Draw,7,
- turn(Colour,Draw,8,
- turn(Colour,Draw,9,Board))))))))}.
-
-turn(Colour,H,D,Board) ->
- case catch is_good_0(Colour,H,dir(H,D),Board) of
- true ->
- turn_0(Colour,H,D,Board);
- false ->
- Board
- end.
-
-turn_0(_,H,D,B) when is_integer(H), is_integer(D), H+D<0 -> B;
-turn_0(_,H,D,B) when is_integer(H), is_integer(D), H+D>63 -> B;
-turn_0(black,H,D,Board) when is_integer(H), is_integer(D) ->
- E = H+D,
- case element(E+1,Board) of
- white -> turn_0(black,H+D,D,swap(black,E,Board));
- _ -> Board
- end;
-turn_0(white,H,D,Board) when is_integer(H), is_integer(D) ->
- E = H+D,
- case element(E+1,Board) of
- black -> turn_0(white,H+D,D,swap(white,E,Board));
- _ -> Board
- end.
-
-%%-------------------------------------------------------
-%% swap(Colour,Pos,Board) - returns an updated board
-%% turn a piece on the board
-%% Neighbours are not changed !!
-%%-------------------------------------------------------
-
-swap(Colour,Pos,Board) when is_integer(Pos) ->
- setelement(Pos+1,Board,Colour).
-
-score(Pos) -> score1({col(Pos),row(Pos)}).
-
-score1({Column,1}) when Column >= 3, Column =< 6 -> 20;
-score1({Column,8}) when Column >= 3, Column =< 6 -> 20;
-score1({1,Line}) when Line >= 3, Line =< 6 -> 20;
-score1({8,Line}) when Line >= 3, Line =< 6 -> 20;
-score1({Column,2}) when Column >= 3, Column =< 6 -> -7;
-score1({Column,7}) when Column >= 3, Column =< 6 -> -7;
-score1({2,Line}) when Line >= 3, Line =< 6 -> -7;
-score1({7,Line}) when Line >= 3, Line =< 6 -> -7;
-score1({Column,Line}) when Column >= 3, Column =< 6,
- Line >= 3, Line =< 6 -> 1;
-score1({1,1}) -> 100;
-score1({1,8}) -> 100;
-score1({8,1}) -> 100;
-score1({8,8}) -> 100;
-score1({2,1}) -> -30;
-score1({7,1}) -> -30;
-score1({1,2}) -> -30;
-score1({8,2}) -> -30;
-score1({1,7}) -> -30;
-score1({8,7}) -> -30;
-score1({2,8}) -> -30;
-score1({7,8}) -> -30;
-score1({2,2}) -> -50;
-score1({7,2}) -> -50;
-score1({2,7}) -> -50;
-score1({7,7}) -> -50.
-
-%%-------------------------------------------------------
-%% dir(Pos,Dir) - return Dir if allowed direction at Pos.
-%% else return false.
-%%-------------------------------------------------------
-
-dir(0,1) -> 1; % {1,1}
-dir(0,8) -> 8;
-dir(0,9) -> 9;
-dir(0,_) -> false;
-
-dir(7,-1) -> -1; % {8,1}
-dir(7,7) -> 7;
-dir(7,8) -> 8;
-dir(7,_) -> false;
-
-dir(56,-8) -> -8; % {1,8}
-dir(56,-7) -> -7;
-dir(56,1) -> 1;
-dir(56,_) -> false;
-
-dir(63,-9) -> -9; % {8,8}
-dir(63,-8) -> -8;
-dir(63,-1) -> -1;
-dir(63,_) -> false;
-
-dir(Pos,-1) when (Pos bsr 3) == 0 -> -1; % {_,1}
-dir(Pos,1) when (Pos bsr 3) == 0 -> 1;
-dir(Pos,7) when (Pos bsr 3) == 0 -> 7;
-dir(Pos,8) when (Pos bsr 3) == 0 -> 8;
-dir(Pos,9) when (Pos bsr 3) == 0 -> 9;
-dir(Pos,_) when (Pos bsr 3) == 0 -> false;
-
-dir(Pos,-9) when (Pos bsr 3) == 7 -> -9; % {_,8}
-dir(Pos,-8) when (Pos bsr 3) == 7 -> -8;
-dir(Pos,-7) when (Pos bsr 3) == 7 -> -7;
-dir(Pos,-1) when (Pos bsr 3) == 7 -> -1;
-dir(Pos,1) when (Pos bsr 3) == 7 -> 1;
-dir(Pos,_) when (Pos bsr 3) == 7 -> false;
-
-dir(Pos,-8) when (Pos band 7) == 0 -> -8; % {1,_}
-dir(Pos,-7) when (Pos band 7) == 0 -> -7;
-dir(Pos,1) when (Pos band 7) == 0 -> 1;
-dir(Pos,8) when (Pos band 7) == 0 -> 8;
-dir(Pos,9) when (Pos band 7) == 0 -> 9;
-dir(Pos,_) when (Pos band 7) == 0 -> false;
-
-dir(Pos,-9) when (Pos band 7) == 7 -> -9; % {8,_}
-dir(Pos,-8) when (Pos band 7) == 7 -> -8;
-dir(Pos,-1) when (Pos band 7) == 7 -> -1;
-dir(Pos,7) when (Pos band 7) == 7 -> 7;
-dir(Pos,8) when (Pos band 7) == 7 -> 8;
-dir(Pos,_) when (Pos band 7) == 7 -> false;
-
-dir(_Pos,Dir) -> Dir.
-
diff --git a/lib/gs/contribs/othello/othello_board.erl b/lib/gs/contribs/othello/othello_board.erl
deleted file mode 100644
index cc055b1fa1..0000000000
--- a/lib/gs/contribs/othello/othello_board.erl
+++ /dev/null
@@ -1,649 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%
--module(othello_board).
--compile([{nowarn_deprecated_function,{gs,config,2}},
- {nowarn_deprecated_function,{gs,create,3}},
- {nowarn_deprecated_function,{gs,create,4}},
- {nowarn_deprecated_function,{gs,destroy,1}},
- {nowarn_deprecated_function,{gs,start,0}}]).
-
--export([start/0,stop/0,init/0]).
-
-
-%%----------------------------------------------------------------------
-%% The Othello program now uses the gs graphical package instead of the
-%% pxw package.
-%%
-%% Differences are, explanation why and source of change in parenthesis:
-%%
-%% - Buttons looks different (gs feature)
-%% - The black box around "Black to draw" have been removed. (me)
-%% - The Colour and Level menues have been moved directly down to the
-%% 'Status' box. (usability update, my addition)
-%% - The mouse pointer does not change into a watch when the computer
-%% is thinking (not supported in gs)
-%% - Buttons does not flash when being beeped. (not supported in gs)
-%%
-%%
-%% /Peter
-%%
-%%----------------------------------------------------------------------
-
-
--define(BGCOL,forestgreen).
-
-start() ->
- spawn(othello_board,init,[]).
-
-stop() ->
- ok.
-
-%% This is not an application so we don't have their way of knowing
-%% a private data directory where the GIF files are located (this directory).
-%% We can find GS and makes it relative from there /kgb
-
--define(BitmapPath,"../contribs/othello/priv").
-
-setup_path() ->
- GsPrivDir = code:priv_dir(gs),
- Path = filename:join(GsPrivDir,?BitmapPath),
- put(path,Path).
-
-path() -> get(path).
-
-
-
-%%
-%% The button area are the Quit, Rules buttons at the top of the window.
-%% The Status area is the black and white scores level and colour etc
-%% inbetween the buttons and the othello board.
-%% The board is the 8x8 board where othello battles are fought.
-%%
-init() ->
- process_flag(trap_exit,true),
- setup_path(),
- S = gs:start(),
- put(windowroot,S), % Ugly global store
-
- %% Shell coordinates
- W = 496,
- H = 636,
-
- %% Fix top window
- Shell = gs:create(window, S, [{title,"Othello"},
- {width, W},{height, H}]),
-
-
- %% Setup window contents
-
- setup_buttons(Shell,0,0,W,40), % Fix Menubar
- setup_status_box(Shell,0,40,W,100), % Fix Status area
- setup_board(Shell,0,140,496,496), % Combat board
-
- GamePid = othello:new_game(white,black,1,first_time),
-
- %% Default settings
- Options = {white,black,1},
- %%Wids = {Status,B,W,Dr,Le,Co},
- Wids = {change,this,at,later,stage,ponto},
- write_options(Options,Wids),
-
- gs:config(Shell, {map, true}), %Make win visible
-
- loop(computer,GamePid,Shell,Wids,Options).
-
-
-
-
-
-
-loop(User,GamePid,Shell,Wids,Options) ->
- receive
- {gs,ButtId, click,_ButtId1,[Button]} ->
- GamePid1 = but_pressed(Button,ButtId,User,GamePid,Shell,
- Wids,Options),
- loop(User,GamePid1,Shell,Wids,Options);
-
- {gs,_, click,_,[MenuItem,_MenuIndex]} ->
- Ops = menu_selected(MenuItem,User,GamePid,Wids,Options),
- loop(User,GamePid,Shell,Wids,Ops);
-
- {'EXIT',GamePid,_} ->
- loop(User,null,Shell,Wids,Options);
-
- {'EXIT',_,_} ->
- loop(User,GamePid,Shell,Wids,Options);
-
- GameMsg ->
- game_msg(GameMsg,User,GamePid,Shell,Wids,Options)
- end.
-
-but_pressed("Quit",_ButtId,_User,_GamePid,_Shell,_Wids,_Op) ->
- stop(),
- exit(quit);
-but_pressed("Rules",_ButtId,_User,GamePid,_Shell,_Wids,_Op) ->
- io:format("No rules, do as you wish~n",[]),
- GamePid;
-but_pressed("Help",_ButtId,_User,GamePid,_Shell,_Wids,_Op) ->
- io:format("Othello game~n",[]),
- io:format("------------~n",[]),
- io:format(" Put markers by clicking in squares~n",[]),
- io:format(" Change level by clicking on it~n",[]),
- io:format(" Change colour by clicking on it~n",[]),
- io:format("~n",[]),
- GamePid;
-but_pressed("Newgame",_ButtId,_User,GamePid,_Shell,Wids,Options) ->
- new_game(GamePid,Wids,Options);
-but_pressed([],ButtId,User,GamePid,_Shell,_Wids,_Op)
- when is_pid(GamePid),User == player ->
- [C,R] = atom_to_list(ButtId),
- GamePid ! {self(),position,othello_adt:pos(C-96,translate(R-48))},
- GamePid;
-but_pressed([],ButtId,_User,GamePid,_Shell,_Wids,_Op) ->
- [C,R] = atom_to_list(ButtId),
- beep(othello_adt:pos(C-96,translate(R-48))),
- GamePid;
-but_pressed(Button,ButtId,_User,GamePid,_Shell,_Wids,_Op) ->
- io:format('Not implemented button pressed ~p, ~p!!!~n',[ButtId,Button]),
- GamePid.
-
-menu_selected("Black",_User,_GamePid,Wids,Options) ->
- Op0 = setelement(1,Options,white),
- Op1 = setelement(2,Op0,white),
- write_options(Op1,Wids),
- Op1;
-menu_selected("White",_User,_GamePid,Wids,Options) ->
- Op0 = setelement(1,Options,black),
- Op1 = setelement(2,Op0,black),
- write_options(Op1,Wids),
- Op1;
-menu_selected("Black (begin)",_User,_GamePid,Wids,Options) ->
- Op0 = setelement(1,Options,white),
- Op1 = setelement(2,Op0,black),
- write_options(Op1,Wids),
- Op1;
-menu_selected("White (begin)",_User,_GamePid,Wids,Options) ->
- Op0 = setelement(1,Options,black),
- Op1 = setelement(2,Op0,white),
- write_options(Op1,Wids),
- Op1;
-menu_selected("Beginner",_User,_GamePid,Wids,Options) ->
- Op1 = setelement(3,Options,1),
- write_options(Op1,Wids),
- Op1;
-menu_selected("Intermediate",_User,_GamePid,Wids,Options) ->
- Op1 = setelement(3,Options,2),
- write_options(Op1,Wids),
- Op1;
-menu_selected("Advanced",_User,_GamePid,Wids,Options) ->
- Op1 = setelement(3,Options,3),
- write_options(Op1,Wids),
- Op1;
-menu_selected("Expert",_User,_GamePid,Wids,Options) ->
- Op1 = setelement(3,Options,4),
- write_options(Op1,Wids),
- Op1;
-menu_selected(What,_User,_GamePid,_Wids,Options) ->
- io:format('Menu item not implemented <~s>~n',[What]),
- Options.
-
-game_msg(Msg,User,GamePid,Shell,Wids,Options) ->
- case Msg of
- {GamePid,new_mark,Pos,Colour} ->
- new_mark(Pos,Colour),
- loop(User,GamePid,Shell,Wids,Options);
-
- {GamePid,illegal_draw,Draw} ->
- beep(Draw),
- loop(User,GamePid,Shell,Wids,Options);
-
- {GamePid,player,Computer,Computer} ->
- show_player(element(1,Wids),Computer),
- cursor("watch"),
- GamePid ! {self(),go_on_play},
- loop(computer,GamePid,Shell,Wids,Options);
-
- {GamePid,player,_Computer,Player} ->
- show_player(element(1,Wids),Player),
- cursor("top_left_arrow"),
- GamePid ! {self(),go_on_play},
- loop(player,GamePid,Shell,Wids,Options);
-
- {GamePid,omit_draw,Player} ->
- omit_draw(GamePid,Player),
- loop(User,GamePid,Shell,Wids,Options);
-
- {GamePid,score,WhiteRes,BlackRes} ->
- write_score(Wids,WhiteRes,BlackRes),
- loop(User,GamePid,Shell,Wids,Options);
-
- {GamePid,draw,Draw} ->
- write_draw(Wids,Draw),
- loop(User,GamePid,Shell,Wids,Options);
-
- {GamePid,game_over,WhiteRes,BlackRes} ->
- game_over(WhiteRes,BlackRes),
- loop(User,GamePid,Shell,Wids,Options);
-
- What ->
- io:format('game_msg received: ~w~n',[What]),
- loop(User,GamePid,Shell,Wids,Options)
- end.
-
-
-new_game(GamePid,Wids,Options) when is_pid(GamePid) ->
- exit(GamePid,kill),
- new_game(Wids,Options);
-new_game(_,Wids,Options) ->
- new_game(Wids,Options).
-
-new_game(_Wids,Options) ->
- label("",lastdraw),
- Computer = element(1,Options),
- Start = element(2,Options),
- Depth = element(3,Options),
- othello:new_game(Computer,Start,Depth,restart).
-
-new_mark(Pos,Colour) ->
- Col = othello_adt:col(Pos),
- Row = othello_adt:row(Pos),
- Name = [Col+96,translate(Row)+48],
- Button = get(Name),
- butbit(Button,Colour).
-
-beep(Draw) ->
- Col = othello_adt:col(Draw),
- Row = othello_adt:row(Draw),
- Name = [Col+96,translate(Row)+48],
- Button = get(Name),
- bell(Button).
-
-show_player(_Status,white) ->
- label("White to draw",todraw);
-show_player(_Status,black) ->
- label("Black to draw",todraw).
-
-write_score(_Wids,WhiteRes,BlackRes) ->
- label(integer_to_list(BlackRes),bscore),
- label(integer_to_list(WhiteRes),wscore).
-
-write_draw(_Wids,Draw) ->
- Col = othello_adt:col(Draw),
- Row = othello_adt:row(Draw),
- label(lists:flatten(io_lib:format('{~w,~w}',[Col,Row])), lastdraw).
-
-write_options(Options,Wids) ->
- write_colour(Options,Wids),
- write_level(Options,Wids).
-
-write_colour(Options,Wids) ->
- write_colour(element(1,Options),element(2,Options),Wids).
-
-write_colour(black,white,_Wids) -> label("White (begin)",colour);
-write_colour(black,black,_Wids) -> label("White",colour);
-write_colour(white,black,_Wids) -> label("Black (begin)",colour);
-write_colour(white,white,_Wids) -> label("Black",colour).
-
-write_level(Options,_Wids) ->
- case element(3,Options) of
- 1 -> label("Beginner",level);
- 2 -> label("Intermediate",level);
- 3 -> label("Advanced",level);
- 4 -> label("Expert",level)
- end.
-
-cursor(_What) ->
- done.
-%cursor(What) -> cursor(get(),What).
-
-%cursor([{[C,R],Button}|Buts],What) ->
-% set_widget(Button,"cursor",What),
-% cursor(Buts,What);
-%cursor([_|Buts],What) ->
-% cursor(Buts,What);
-%cursor([],_) ->
-% true.
-
-translate(1) -> 8;
-translate(2) -> 7;
-translate(3) -> 6;
-translate(4) -> 5;
-translate(5) -> 4;
-translate(6) -> 3;
-translate(7) -> 2;
-translate(8) -> 1.
-
-bitmap(grey) -> bitmap_path("square.bm");
-bitmap(black) -> bitmap_path("marker.bm");
-bitmap(white) -> bitmap_path("marker.bm").
-
-bitmap_path(Bitmap) ->
- filename:join(path(),Bitmap).
-
-xy_position([[Letter,Digit],_,_]) ->
- LettPos = Letter - 97,
- X = LettPos*60 ,
- Y = (8 - list_to_integer([Digit])) * 60,
- {X+6,Y+6};
-xy_position(X) ->
- io:format("xy_position: ~w~n",[{error,X}]).
-
-
-board() ->
- [["a1",grey,nil],
- ["b1",grey,nil],
- ["c1",grey,nil],
- ["d1",grey,nil],
- ["e1",grey,nil],
- ["f1",grey,nil],
- ["g1",grey,nil],
- ["h1",grey,nil],
-
- ["a2",grey,nil],
- ["b2",grey,nil],
- ["c2",grey,nil],
- ["d2",grey,nil],
- ["e2",grey,nil],
- ["f2",grey,nil],
- ["g2",grey,nil],
- ["h2",grey,nil],
-
- ["a3",grey,nil],
- ["b3",grey,nil],
- ["c3",grey,nil],
- ["d3",grey,nil],
- ["e3",grey,nil],
- ["f3",grey,nil],
- ["g3",grey,nil],
- ["h3",grey,nil],
-
- ["a4",grey,nil],
- ["b4",grey,nil],
- ["c4",grey,nil],
- ["d4",white,nil],
- ["e4",black,nil],
- ["f4",grey,nil],
- ["g4",grey,nil],
- ["h4",grey,nil],
-
- ["a5",grey,nil],
- ["b5",grey,nil],
- ["c5",grey,nil],
- ["d5",black,nil],
- ["e5",white,nil],
- ["f5",grey,nil],
- ["g5",grey,nil],
- ["h5",grey,nil],
-
- ["a6",grey,nil],
- ["b6",grey,nil],
- ["c6",grey,nil],
- ["d6",grey,nil],
- ["e6",grey,nil],
- ["f6",grey,nil],
- ["g6",grey,nil],
- ["h6",grey,nil],
-
- ["a7",grey,nil],
- ["b7",grey,nil],
- ["c7",grey,nil],
- ["d7",grey,nil],
- ["e7",grey,nil],
- ["f7",grey,nil],
- ["g7",grey,nil],
- ["h7",grey,nil],
-
- ["a8",grey,nil],
- ["b8",grey,nil],
- ["c8",grey,nil],
- ["d8",grey,nil],
- ["e8",grey,nil],
- ["f8",grey,nil],
- ["g8",grey,nil],
- ["h8",grey,nil]].
-
-
-omit_draw(GamePid,Player) ->
-% %% Find mouse coords first
-% %% This was not possible in gs
-
- W = 200, H = 100, Root = get(windowroot),
- Box = gs:create(window, Root, [{title,"OMIT"}, {width, W},{height, H}]),
-
- mk_label_c(lists:flatten(io_lib:format('~w has to omit draw !',[Player])),
- Box, W, 10),
-
- mk_button_c("Ok", Box, W, H-40, 80, 30),
-
- gs:config(Box, {map, true}), %Make win visible
-
- receive
- {gs,_, click,_,["Ok"]} ->
- gs:destroy(Box),
- GamePid ! {self(),continue}
- end.
-
-game_over(WhiteRes,BlackRes) ->
-% %% Find mouse coords first
-% %% This was not possible in gs
-
- W = 200, H = 160,
- Root = get(windowroot),
- Box = gs:create(window, Root, [{title,"GAME OVER"},
- {width, W},{height, H}]),
-
- mk_label_c("GAME OVER", Box, W, 10),
-
- mk_label_c(lists:flatten(io_lib:format('White score: ~w',[WhiteRes])),
- Box,W,40),
- mk_label_c(lists:flatten(io_lib:format('Black score: ~w',[BlackRes])),
- Box,W,70),
-
- mk_button_c("Ok", Box, W, H-40, 80, 30),
-
- gs:config(Box, {map, true}), %Make win visible
-
- receive
- {gs,_, click,_,["Ok"]} ->
- gs:destroy(Box)
- end.
-
-
-
-%% ----------------------------------------------------------------
-%% Library functions.
-%% ----------------------------------------------------------------
-
-bell(Widget) ->
- %% gs does not support bells,
- Widget.
-
-label(Text,Label) ->
- gs:config(Label,[{label,{text,Text}}]).
-
-%% mk_label in centered version
-mk_label_c(Label,Parent,Width,Y) ->
- W = 8*length(Label),
- X = trunc((Width-W)/2),
- gs:create(label,Parent,[{width,W}, {height, 20}, {x,X}, {y,Y},
- {label, {text, Label}}]).
-
-
-
-
-setup_buttons(Shell,X,Y,W,H) ->
- ButBox = gs:create(frame, Shell,[{x,X}, {y,Y},{bg,white},
- {width,W}, {height,H}]),
- C = gs:create(canvas,ButBox,[{x,X}, {y,Y}, {width, W}, {height, H},
- {bg,white}]),
- gs:create(line, C, [{coords, [{0,H-1},{W,H-1}]}]),
-
-
- mk_button("Quit",ButBox, 10, 10, 70, 20),
- mk_button("Rules",ButBox, 80, 10, 70, 20),
- mk_button("Newgame",ButBox, 150, 10, 70, 20),
- mk_button("Help",ButBox, 220, 10, 70, 20),
-%% mk_button("Level",ButBox, 290, 10, 70, 20),
-
- done.
-
-
-
-
-
-%%----------------------------------------
-%% Sets up the middle window w. all the status info in.
-%% The labels are given names:
-%% bscore, wscore, lastdraw, todraw, level and colour to simplify
-%% their frequent setting
-%%
-setup_status_box(Shell,X,Y,W,H) ->
- F = gs:create(frame, Shell,[{x,X}, {y,Y},
- {width,W}, {height,H},{bg,white}]),
- C = gs:create(canvas,F,[{x,0}, {y,0}, {width, W}, {height, H},{bg,white}]),
- gs:create(line, C, [{coords, [{0,H-1},{W,H-1}]}]),
-
- %% Left side
- gs:create(label,F,[{align,w},{x,10}, {y,5}, {width, 100},
- {label,{text, "Black score:"}},{bg,white}]),
- gs:create(label,bscore,F,[{align,w},{x,110}, {y,5}, {width, 40},
- {label,{text, "2"}},{bg,white}]),
- gs:create(label,F,[{align,w},{x,10}, {y,35}, {width, 100},
- {label,{text, "White score:"}},{bg,white}]),
- gs:create(label,wscore,F,[{align,w},{x,110}, {y,35}, {width, 40},
- {label,{text, "2"}},{bg,white}]),
- gs:create(label,F,[{align,w},{x,10}, {y,65}, {width, 100},
- {label,{text, "Last draw:"}},{bg,white}]),
- gs:create(label,lastdraw,F,[{align,w},{x,110}, {y,65}, {width, 40},
- {label,{text, ""}},{bg,white}]),
-
-
- %% Right side
- X2 = trunc(W/2)+10,
- gs:create(label,todraw,F,[{align,w},{x,X2}, {y,5}, {width, 100},
- {label,{text, "Black to draw:"}},{bg,white}]),
-
- gs:create(label,F,[{align,w},{x,X2}, {y,35}, {width, 80},
- {label,{text, "Level:"}},{bg,white}]),
- setup_level_menu(F,X2+80,35),
-
-%% gs:create(label,level,F,[{align,w},{x,X2+80}, {y,35}, {width, 130},
-%% {label,{text, "Intermediate"}},{bg,white}]),
- gs:create(label,F,[{align,w},{x,X2}, {y,65}, {width, 80},
- {label,{text, "Colour:"}},{bg,white}]),
- setup_col_menu(F,X2+80,65),
-
-%% gs:create(label,colour,F,[{align,w},{x,X2+80}, {y,65}, {width, 120},
-%% {label,{text, "black (begin)"}},{bg,white}]),
-
- done.
-
-
-setup_col_menu(P,X,Y) ->
- MB = gs:create(menubutton,colour,P,
- [{x,X}, {y,Y}, {bw,3},
- %%{width,W}, {height,H},
- {align,w}, {bg,white},
- {relief, raised},
- {activefg,white}, {activebg,black},
- {label, {text,"Colours"}}]),
-
- M = gs:create(menu,MB,[]),
- gs:create(menuitem,M,[{label,{text,"Black (begin)"}}]),
- gs:create(menuitem,M,[{label,{text,"Black"}}]),
- gs:create(menuitem,M,[{label,{text,"White (begin)"}}]),
- gs:create(menuitem,M,[{label,{text,"White"}}]),
- done.
-
-setup_level_menu(P,X,Y) ->
- MB = gs:create(menubutton,level,P,
- [{x,X}, {y,Y},
- %%{width,W}, {height,H},
- {relief, raised},
- {activefg,white}, {activebg,black},
- {align,w}, {bg,white},
- {label, {text,"Colours"}}]),
-
- M = gs:create(menu,MB,[]),
- gs:create(menuitem,M,[{label,{text,"Beginner"}}]),
- gs:create(menuitem,M,[{label,{text,"Intermediate"}}]),
- gs:create(menuitem,M,[{label,{text,"Advanced"}}]),
- gs:create(menuitem,M,[{label,{text,"Expert"}}]),
- done.
-
-
-setup_board(Shell,X,Y,W,H) ->
- F = gs:create(frame, Shell,[{x,X}, {y,Y},
- {width,W}, {height,H},{bg,white}]),
- display_board(F).
-
-
-mk_button(Label, Parent, X, Y, W, H) ->
- gs:create(button,Parent,[{width,W}, {height, H}, {x,X}, {y,Y},
- {label, {text, Label}}, {bg,white},
- {activefg,white}, {activebg,black}]).
-
-%% Centers a button around Width
-mk_button_c(Label, Parent, Width, Y, W, H) ->
- X = trunc((Width-W)/2),
- gs:create(button,Parent,[{width,W}, {height, H}, {x,X}, {y,Y},
- {label, {text, Label}}, {bg,white}]).
-
-
-butbit(Button,Col) ->
- gs:config(Button,[
- {label,{image,bitmap(Col)}},
- {fg, Col},
- {activefg,Col},
- {label, {image, bitmap(Col)}}]),
- Button.
-
-mk_board_butt(Top,Name,X,Y,Col) ->
- B = gs:create(button,list_to_atom(Name), Top,
- [{x,X}, {y,Y}, {width,60}, {height,60},
- {padx,5},{pady,5},
- {relief,flat},
- {bg,?BGCOL}, {activebg,?BGCOL}]),
- butbit(B,Col),
- B.
-
-
-
-display_board(Top) ->
- Board = board(),
- display_board(Top,Board,1).
-
-display_board(_,_,65) -> true;
-display_board(Top,[H|T],Place) ->
- [Name,Colour,_] = H,
- {X,Y} = xy_position(H),
- Button = mk_board_butt(Top,Name,X,Y,Colour),
- %%Button = mk_button("",Name,Top,X,Y,60,60),
- put(Name,Button),
- %%Bitmap = bitmap(Colour),
- %%butbit(Button,Bitmap),
- %%set_widget(Button,"internalWidth","1"),
- %%set_widget(Button,"internalHeight","1"),
- %%borderWidth(2,Button),
- display_board(Top,T,Place+1).
-
-
diff --git a/lib/gs/contribs/othello/priv/marker.bm b/lib/gs/contribs/othello/priv/marker.bm
deleted file mode 100644
index fe7f3df820..0000000000
--- a/lib/gs/contribs/othello/priv/marker.bm
+++ /dev/null
@@ -1,43 +0,0 @@
-#define marker2_width 60
-#define marker2_height 60
-static unsigned char marker2_bits[] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x0f, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xc0, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff,
- 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0x0f, 0x00, 0x00,
- 0x00, 0x00, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff,
- 0xff, 0x3f, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
- 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0xf8, 0xff, 0xff,
- 0xff, 0xff, 0x03, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00,
- 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0xfe, 0xff, 0xff,
- 0xff, 0xff, 0x0f, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00,
- 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x80, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0x3f, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00,
- 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0xc0, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0x7f, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00,
- 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0xe0, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
- 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xe0, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
- 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xe0, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
- 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xe0, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
- 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7e, 0x00, 0xc0, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0x7f, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x7f, 0x00,
- 0x80, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x3f, 0x00, 0x80, 0xff, 0xff, 0xff,
- 0xff, 0x3f, 0x3f, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x3f, 0x00,
- 0x00, 0xff, 0xff, 0xff, 0xff, 0x9f, 0x1f, 0x00, 0x00, 0xff, 0xff, 0xff,
- 0xff, 0xcf, 0x1f, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xc7, 0x0f, 0x00,
- 0x00, 0xfc, 0xff, 0xff, 0xff, 0xe7, 0x07, 0x00, 0x00, 0xf8, 0xff, 0xff,
- 0x7f, 0xf1, 0x03, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xbf, 0xfc, 0x03, 0x00,
- 0x00, 0xf0, 0xff, 0xff, 0x59, 0xff, 0x01, 0x00, 0x00, 0xe0, 0xff, 0xff,
- 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00,
- 0x00, 0x00, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff,
- 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x03, 0x00, 0x00,
- 0x00, 0x00, 0xc0, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe,
- 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/lib/gs/contribs/othello/priv/square.bm b/lib/gs/contribs/othello/priv/square.bm
deleted file mode 100644
index 4e6880b330..0000000000
--- a/lib/gs/contribs/othello/priv/square.bm
+++ /dev/null
@@ -1,43 +0,0 @@
-#define square_width 60
-#define square_height 60
-static unsigned char square_bits[] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/lib/hipe/cerl/erl_types.erl b/lib/hipe/cerl/erl_types.erl
index 420d7e2a8f..ab5a57dc3d 100644
--- a/lib/hipe/cerl/erl_types.erl
+++ b/lib/hipe/cerl/erl_types.erl
@@ -140,7 +140,6 @@
t_is_port/1, t_is_port/2,
t_is_maybe_improper_list/1, t_is_maybe_improper_list/2,
t_is_reference/1, t_is_reference/2,
- t_is_remote/1,
t_is_string/1,
t_is_subtype/2,
t_is_tuple/1, t_is_tuple/2,
@@ -180,7 +179,6 @@
%% t_maybe_improper_list/2,
t_product/1,
t_reference/0,
- t_remote/3,
t_string/0,
t_struct_from_opaque/2,
t_subst/2,
@@ -208,7 +206,6 @@
type_is_defined/4,
record_field_diffs_to_string/2,
subst_all_vars_to_any/1,
- subst_all_remote/2,
lift_list_to_pos_empty/1, lift_list_to_pos_empty/2,
is_opaque_type/2,
is_erl_type/1,
@@ -280,7 +277,6 @@
-define(number_tag, number).
-define(opaque_tag, opaque).
-define(product_tag, product).
--define(remote_tag, remote).
-define(tuple_set_tag, tuple_set).
-define(tuple_tag, tuple).
-define(union_tag, union).
@@ -288,7 +284,7 @@
-type tag() :: ?atom_tag | ?binary_tag | ?function_tag | ?identifier_tag
| ?list_tag | ?map_tag | ?matchstate_tag | ?nil_tag | ?number_tag
- | ?opaque_tag | ?product_tag | ?remote_tag
+ | ?opaque_tag | ?product_tag
| ?tuple_tag | ?tuple_set_tag | ?union_tag | ?var_tag.
-define(float_qual, float).
@@ -330,7 +326,6 @@
%% was updated to 2.7 due to this change.
-record(opaque, {mod :: module(), name :: atom(),
args = [] :: [erl_type()], struct :: erl_type()}).
--record(remote, {mod:: module(), name :: atom(), args = [] :: [erl_type()]}).
-define(atom(Set), #c{tag=?atom_tag, elements=Set}).
-define(bitstr(Unit, Base), #c{tag=?binary_tag, elements=[Unit,Base]}).
@@ -350,7 +345,6 @@
-define(map(Pairs), #c{tag=?map_tag, elements=Pairs}).
-define(opaque(Optypes), #c{tag=?opaque_tag, elements=Optypes}).
-define(product(Types), #c{tag=?product_tag, elements=Types}).
--define(remote(RemTypes), #c{tag=?remote_tag, elements=RemTypes}).
-define(tuple(Types, Arity, Qual), #c{tag=?tuple_tag, elements=Types,
qualifier={Arity, Qual}}).
-define(tuple_set(Tuples), #c{tag=?tuple_set_tag, elements=Tuples}).
@@ -380,19 +374,18 @@
%% Unions
%%
--define(union(List), #c{tag=?union_tag, elements=[_,_,_,_,_,_,_,_,_,_,_]=List}).
-
--define(atom_union(T), ?union([T,?none,?none,?none,?none,?none,?none,?none,?none,?none,?none])).
--define(bitstr_union(T), ?union([?none,T,?none,?none,?none,?none,?none,?none,?none,?none,?none])).
--define(function_union(T), ?union([?none,?none,T,?none,?none,?none,?none,?none,?none,?none,?none])).
--define(identifier_union(T), ?union([?none,?none,?none,T,?none,?none,?none,?none,?none,?none,?none])).
--define(list_union(T), ?union([?none,?none,?none,?none,T,?none,?none,?none,?none,?none,?none])).
--define(number_union(T), ?union([?none,?none,?none,?none,?none,T,?none,?none,?none,?none,?none])).
--define(tuple_union(T), ?union([?none,?none,?none,?none,?none,?none,T,?none,?none,?none,?none])).
--define(matchstate_union(T), ?union([?none,?none,?none,?none,?none,?none,?none,T,?none,?none,?none])).
--define(opaque_union(T), ?union([?none,?none,?none,?none,?none,?none,?none,?none,T,?none,?none])).
--define(remote_union(T), ?union([?none,?none,?none,?none,?none,?none,?none,?none,?none,T,?none])).
--define(map_union(T), ?union([?none,?none,?none,?none,?none,?none,?none,?none,?none,?none,T])).
+-define(union(List), #c{tag=?union_tag, elements=[_,_,_,_,_,_,_,_,_,_]=List}).
+
+-define(atom_union(T), ?union([T,?none,?none,?none,?none,?none,?none,?none,?none,?none])).
+-define(bitstr_union(T), ?union([?none,T,?none,?none,?none,?none,?none,?none,?none,?none])).
+-define(function_union(T), ?union([?none,?none,T,?none,?none,?none,?none,?none,?none,?none])).
+-define(identifier_union(T), ?union([?none,?none,?none,T,?none,?none,?none,?none,?none,?none])).
+-define(list_union(T), ?union([?none,?none,?none,?none,T,?none,?none,?none,?none,?none])).
+-define(number_union(T), ?union([?none,?none,?none,?none,?none,T,?none,?none,?none,?none])).
+-define(tuple_union(T), ?union([?none,?none,?none,?none,?none,?none,T,?none,?none,?none])).
+-define(matchstate_union(T), ?union([?none,?none,?none,?none,?none,?none,?none,T,?none,?none])).
+-define(opaque_union(T), ?union([?none,?none,?none,?none,?none,?none,?none,?none,T,?none])).
+-define(map_union(T), ?union([?none,?none,?none,?none,?none,?none,?none,?none,?none,T])).
-define(integer_union(T), ?number_union(T)).
-define(float_union(T), ?number_union(T)).
-define(nil_union(T), ?list_union(T)).
@@ -679,8 +672,8 @@ list_decorate(List, L, Opaques) ->
union_decorate(U1, U2, Opaques) ->
Union = union_decorate(U1, U2, Opaques, 0, []),
- [A,B,F,I,L,N,T,M,_,_R,Map] = U1,
- [_,_,_,_,_,_,_,_,Opaque,_,_] = U2,
+ [A,B,F,I,L,N,T,M,_,Map] = U1,
+ [_,_,_,_,_,_,_,_,Opaque,_] = U2,
List = [A,B,F,I,L,N,T,M,Map],
DecList = [Dec ||
E <- List,
@@ -792,21 +785,6 @@ list_struct_from_opaque(Types, Opaques) ->
[t_struct_from_opaque(Type, Opaques) || Type <- Types].
%%-----------------------------------------------------------------------------
-%% Remote types: these types are used for preprocessing;
-%% they should never reach the analysis stage.
-
--spec t_remote(atom(), atom(), [erl_type()]) -> erl_type().
-
-t_remote(Mod, Name, Args) ->
- ?remote(set_singleton(#remote{mod = Mod, name = Name, args = Args})).
-
--spec t_is_remote(erl_type()) -> boolean().
-
-t_is_remote(Type) ->
- do_opaque(Type, 'universe', fun is_remote/1).
-
-is_remote(?remote(_)) -> true;
-is_remote(_) -> false.
-type mod_records() :: dict:dict(module(), type_table()).
@@ -2178,8 +2156,6 @@ t_sup(?opaque(Set1), ?opaque(Set2)) ->
%% io:format("Debug: t_sup executed with args ~w and ~w~n",[T1, T2]), ?none;
%%t_sup(T1, T2=?opaque(_,_,_)) ->
%% io:format("Debug: t_sup executed with args ~w and ~w~n",[T1, T2]), ?none;
-t_sup(?remote(Set1), ?remote(Set2)) ->
- ?remote(set_union_no_limit(Set1, Set2));
t_sup(?matchstate(Pres1, Slots1), ?matchstate(Pres2, Slots2)) ->
?matchstate(t_sup(Pres1, Pres2), t_sup(Slots1, Slots2));
t_sup(?nil, ?nil) -> ?nil;
@@ -2373,7 +2349,6 @@ force_union(T = ?list(_, _, _)) -> ?list_union(T);
force_union(T = ?nil) -> ?list_union(T);
force_union(T = ?number(_, _)) -> ?number_union(T);
force_union(T = ?opaque(_)) -> ?opaque_union(T);
-force_union(T = ?remote(_)) -> ?remote_union(T);
force_union(T = ?map(_)) -> ?map_union(T);
force_union(T = ?tuple(_, _, _)) -> ?tuple_union(T);
force_union(T = ?tuple_set(_)) -> ?tuple_union(T);
@@ -2880,8 +2855,8 @@ inf_tuples_in_sets2(_, [], Acc, _Opaques) -> lists:reverse(Acc).
inf_union(U1, U2, Opaques) ->
OpaqueFun =
fun(Union1, Union2, InfFun) ->
- [_,_,_,_,_,_,_,_,Opaque,_,_] = Union1,
- [A,B,F,I,L,N,T,M,_,_R,Map] = Union2,
+ [_,_,_,_,_,_,_,_,Opaque,_] = Union1,
+ [A,B,F,I,L,N,T,M,_,Map] = Union2,
List = [A,B,F,I,L,N,T,M,Map],
inf_union_collect(List, Opaque, InfFun, [], [])
end,
@@ -3060,18 +3035,6 @@ t_subst_aux(?union(List), VarMap) ->
?union([t_subst_aux(E, VarMap) || E <- List]);
t_subst_aux(T, _VarMap) ->
T.
-
--spec subst_all_remote(erl_type(), erl_type()) -> erl_type().
-
-subst_all_remote(Type0, Substitute) ->
- Map =
- fun(Type) ->
- case t_is_remote(Type) of
- true -> Substitute;
- false -> Type
- end
- end,
- t_map(Map, Type0).
%%-----------------------------------------------------------------------------
%% Unification
@@ -3175,11 +3138,11 @@ unify_union1(?union(List), T1, T2) ->
end.
unify_union(List) ->
- [A,B,F,I,L,N,T,M,O,R,Map] = List,
+ [A,B,F,I,L,N,T,M,O,Map] = List,
if O =:= ?none -> no;
true ->
S = t_opaque_structure(O),
- {yes, t_sup([A,B,F,I,L,N,T,M,S,R,Map])}
+ {yes, t_sup([A,B,F,I,L,N,T,M,S,Map])}
end.
-spec is_opaque_type(erl_type(), [erl_type()]) -> boolean().
@@ -3537,10 +3500,10 @@ t_subtract_lists([], [], Acc) ->
-spec subtract_union([erl_type(),...], [erl_type(),...]) -> erl_type().
subtract_union(U1, U2) ->
- [A1,B1,F1,I1,L1,N1,T1,M1,O1,R1,Map1] = U1,
- [A2,B2,F2,I2,L2,N2,T2,M2,O2,R2,Map2] = U2,
- List1 = [A1,B1,F1,I1,L1,N1,T1,M1,?none,R1,Map1],
- List2 = [A2,B2,F2,I2,L2,N2,T2,M2,?none,R2,Map2],
+ [A1,B1,F1,I1,L1,N1,T1,M1,O1,Map1] = U1,
+ [A2,B2,F2,I2,L2,N2,T2,M2,O2,Map2] = U2,
+ List1 = [A1,B1,F1,I1,L1,N1,T1,M1,?none,Map1],
+ List2 = [A2,B2,F2,I2,L2,N2,T2,M2,?none,Map2],
Sub1 = subtract_union(List1, List2, 0, []),
O = if O1 =:= ?none -> O1;
true -> t_subtract(O1, ?union(U2))
@@ -3656,7 +3619,7 @@ t_unopaque(?product(Types), Opaques) ->
?product([t_unopaque(T, Opaques) || T <- Types]);
t_unopaque(?function(Domain, Range), Opaques) ->
?function(t_unopaque(Domain, Opaques), t_unopaque(Range, Opaques));
-t_unopaque(?union([A,B,F,I,L,N,T,M,O,R,Map]), Opaques) ->
+t_unopaque(?union([A,B,F,I,L,N,T,M,O,Map]), Opaques) ->
UL = t_unopaque(L, Opaques),
UT = t_unopaque(T, Opaques),
UF = t_unopaque(F, Opaques),
@@ -3665,7 +3628,7 @@ t_unopaque(?union([A,B,F,I,L,N,T,M,O,R,Map]), Opaques) ->
?opaque(_) = O1 -> {O1, []};
Type -> {?none, [Type]}
end,
- t_sup([?union([A,B,UF,I,UL,N,UT,M,OF,R,UMap])|UO]);
+ t_sup([?union([A,B,UF,I,UL,N,UT,M,OF,UMap])|UO]);
t_unopaque(T, _) ->
T.
@@ -3932,16 +3895,6 @@ t_to_string(?float, _RecDict) -> "float()";
t_to_string(?number(?any, ?unknown_qual), _RecDict) -> "number()";
t_to_string(?product(List), RecDict) ->
"<" ++ comma_sequence(List, RecDict) ++ ">";
-t_to_string(?remote(Set), RecDict) ->
- string:join([case Args =:= [] of
- true -> flat_format("~w:~w()", [Mod, Name]);
- false ->
- ArgString = comma_sequence(Args, RecDict),
- flat_format("~w:~w(~s)", [Mod, Name, ArgString])
- end
- || #remote{mod = Mod, name = Name, args = Args} <-
- set_to_list(Set)],
- " | ");
t_to_string(?map(Pairs), RecDict) ->
"#{" ++ map_pairs_to_string(Pairs,RecDict) ++ "}";
t_to_string(?tuple(?any, ?any, ?any), _RecDict) -> "tuple()";
@@ -4824,13 +4777,13 @@ do_opaque(?opaque(_) = Type, Opaques, Pred) ->
false -> Pred(Type)
end;
do_opaque(?union(List) = Type, Opaques, Pred) ->
- [A,B,F,I,L,N,T,M,O,R,Map] = List,
+ [A,B,F,I,L,N,T,M,O,Map] = List,
if O =:= ?none -> Pred(Type);
true ->
case Opaques =:= 'universe' orelse is_opaque_type(O, Opaques) of
true ->
S = t_opaque_structure(O),
- do_opaque(t_sup([A,B,F,I,L,N,T,M,S,R,Map]), Opaques, Pred);
+ do_opaque(t_sup([A,B,F,I,L,N,T,M,S,Map]), Opaques, Pred);
false -> Pred(Type)
end
end;
@@ -4864,10 +4817,6 @@ set_union(S1, S2) ->
_ -> ?any
end.
-set_union_no_limit(?any, _) -> ?any;
-set_union_no_limit(_, ?any) -> ?any;
-set_union_no_limit(S1, S2) -> ordsets:union(S1, S2).
-
%% The intersection and subtraction can return ?none.
%% This should always be handled right away since ?none is not a valid set.
%% However, ?any is considered a valid set.
diff --git a/lib/hipe/icode/hipe_icode.erl b/lib/hipe/icode/hipe_icode.erl
index 9692eebb10..07d230491d 100644
--- a/lib/hipe/icode/hipe_icode.erl
+++ b/lib/hipe/icode/hipe_icode.erl
@@ -1376,12 +1376,12 @@ remove_constants(L) ->
%% Substitution: replace occurrences of X by Y if {X,Y} is in the
%% Subst_list.
--spec subst([{_,_}], I) -> I when is_subtype(I, icode_instr()).
+-spec subst([{_,_}], I) -> I when I :: icode_instr().
subst(Subst, I) ->
subst_defines(Subst, subst_uses(Subst, I)).
--spec subst_uses([{_,_}], I) -> I when is_subtype(I, icode_instr()).
+-spec subst_uses([{_,_}], I) -> I when I :: icode_instr().
subst_uses(Subst, I) ->
case I of
@@ -1405,7 +1405,7 @@ subst_uses(Subst, I) ->
#icode_label{} -> I
end.
--spec subst_defines([{_,_}], I) -> I when is_subtype(I, icode_instr()).
+-spec subst_defines([{_,_}], I) -> I when I :: icode_instr().
subst_defines(Subst, I) ->
case I of
diff --git a/lib/hipe/rtl/Makefile b/lib/hipe/rtl/Makefile
index d2517b13fc..1bf52fe312 100644
--- a/lib/hipe/rtl/Makefile
+++ b/lib/hipe/rtl/Makefile
@@ -75,7 +75,7 @@ TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR))
include ../native.mk
-ERL_COMPILE_FLAGS += +inline +warn_unused_import +warn_exported_vars
+ERL_COMPILE_FLAGS += -Werror +inline +warn_unused_import +warn_exported_vars
# ----------------------------------------------------
# Targets
diff --git a/lib/hipe/rtl/hipe_rtl_binary_match.erl b/lib/hipe/rtl/hipe_rtl_binary_match.erl
index 364aab1b6f..51213b71d1 100644
--- a/lib/hipe/rtl/hipe_rtl_binary_match.erl
+++ b/lib/hipe/rtl/hipe_rtl_binary_match.erl
@@ -2,7 +2,7 @@
%%%
%%% %CopyrightBegin%
%%%
-%%% Copyright Ericsson AB 2007-2013. All Rights Reserved.
+%%% Copyright Ericsson AB 2007-2015. All Rights Reserved.
%%%
%%% Licensed under the Apache License, Version 2.0 (the "License");
%%% you may not use this file except in compliance with the License.
@@ -181,17 +181,20 @@ gen_rtl({bs_get_binary, Size, Flags}, [Dst, NewMs], Args,
[hipe_rtl:mk_goto(FalseLblName)];
false ->
Unsafe = unsafe(Flags),
- case Args of
- [Ms] ->
- SizeReg = hipe_rtl:mk_new_reg(),
- SizeCode = [hipe_rtl:mk_move(SizeReg, hipe_rtl:mk_imm(Size))];
- [Ms, BitsVar] ->
- {SizeCode, SizeReg} = make_size(Size, BitsVar, FalseLblName)
- end,
- InCode = get_binary(Dst, Ms, SizeReg, Unsafe,
+ {OldMs, SizeReg, SizeCode} =
+ case Args of
+ [Ms] ->
+ SzReg = hipe_rtl:mk_new_reg(),
+ SzCode = [hipe_rtl:mk_move(SzReg, hipe_rtl:mk_imm(Size))],
+ {Ms, SzReg, SzCode};
+ [Ms, BitsVar] ->
+ {SzCode, SzReg} = make_size(Size, BitsVar, FalseLblName),
+ {Ms, SzReg, SzCode}
+ end,
+ InCode = get_binary(Dst, OldMs, SizeReg, Unsafe,
TrueLblName, FalseLblName),
[hipe_rtl:mk_gctest(?SUB_BIN_WORDSIZE)] ++
- update_ms(NewMs, Ms) ++ SizeCode ++ InCode
+ update_ms(NewMs, OldMs) ++ SizeCode ++ InCode
end;
%% ----- bs_get_utf8 -----
gen_rtl(bs_get_utf8, [Dst, NewMs], [Ms], TrueLblName, FalseLblName) ->
@@ -230,14 +233,26 @@ gen_rtl({bs_skip_bits_all, Unit, _Flags}, Dst, [Ms],
skip_bits_all(Unit, Ms, TrueLblName, FalseLblName);
%% ----- bs_skip_bits -----
gen_rtl({bs_skip_bits, Bits}, Dst, [Ms|Args], TrueLblName, FalseLblName) ->
+ MaxValue = (1 bsl (hipe_rtl_arch:word_size() * ?BYTE_SIZE)),
opt_update_ms(Dst, Ms) ++
- case Args of
- [] ->
- skip_bits2(Ms, hipe_rtl:mk_imm(Bits), TrueLblName, FalseLblName);
- [Arg] ->
- {SizeCode, SizeReg} = make_size(Bits, Arg, FalseLblName),
- InCode = skip_bits2(Ms, SizeReg, TrueLblName, FalseLblName),
- SizeCode ++ InCode
+ case Bits < MaxValue of
+ true ->
+ case Args of
+ [] ->
+ skip_bits2(Ms, hipe_rtl:mk_imm(Bits), TrueLblName, FalseLblName);
+ [Arg] ->
+ {SizeCode, SizeReg} = make_size(Bits, Arg, FalseLblName),
+ InCode = skip_bits2(Ms, SizeReg, TrueLblName, FalseLblName),
+ SizeCode ++ InCode
+ end;
+ false -> % handle overflow case
+ case Args of
+ [] ->
+ [hipe_rtl:mk_goto(FalseLblName)];
+ [Arg] ->
+ [hipe_rtl:mk_branch(Arg, 'eq', hipe_tagscheme:mk_fixnum(0),
+ TrueLblName, FalseLblName, 0.5)]
+ end
end;
%% ----- bs_restore -----
gen_rtl({bs_restore, Slot}, [NewMs], [Ms], TrueLblName, _FalseLblName) ->
@@ -1086,23 +1101,47 @@ create_gcsafe_regs(0) ->
[].
first_part(Var, Register, FalseLblName) ->
- [SuccessLbl1, SuccessLbl2] = create_lbls(2),
- [hipe_tagscheme:test_fixnum(Var, hipe_rtl:label_name(SuccessLbl1),
- FalseLblName, 0.99),
- SuccessLbl1,
- hipe_tagscheme:fixnum_ge(Var, hipe_rtl:mk_imm(hipe_tagscheme:mk_fixnum(0)),
- hipe_rtl:label_name(SuccessLbl2), FalseLblName, 0.99),
- SuccessLbl2,
- hipe_tagscheme:untag_fixnum(Register, Var)].
+ [EndLbl] = create_lbls(1),
+ EndName = hipe_rtl:label_name(EndLbl),
+ first_part(Var, Register, FalseLblName, EndName, EndName, [EndLbl]).
+
+first_part(Var, Register, FalseLblName, TrueLblName, BigLblName, Tail) ->
+ [FixnumLbl, NotFixnumLbl, BignumLbl, SuccessLbl] = create_lbls(4),
+ [hipe_tagscheme:test_fixnum(Var, hipe_rtl:label_name(FixnumLbl),
+ hipe_rtl:label_name(NotFixnumLbl), 0.99),
+ FixnumLbl,
+ hipe_tagscheme:fixnum_ge(Var, hipe_rtl:mk_imm(hipe_tagscheme:mk_fixnum(0)),
+ hipe_rtl:label_name(SuccessLbl), FalseLblName,
+ 0.99),
+ SuccessLbl,
+ hipe_tagscheme:untag_fixnum(Register, Var),
+ hipe_rtl:mk_goto(TrueLblName),
+ NotFixnumLbl,
+ %% Since binaries are not allowed to be larger than 2^wordsize bits
+ %% and since bignum digits are words, we know that a bignum with an
+ %% arity larger than one can't match.
+ hipe_tagscheme:test_pos_bignum_arity(Var, 1, hipe_rtl:label_name(BignumLbl),
+ FalseLblName, 0.99),
+ BignumLbl,
+ hipe_tagscheme:unsafe_get_one_word_pos_bignum(Register, Var),
+ hipe_rtl:mk_goto(BigLblName) | Tail].
make_size(1, BitsVar, FalseLblName) ->
[DstReg] = create_regs(1),
{first_part(BitsVar, DstReg, FalseLblName), DstReg};
make_size(?BYTE_SIZE, BitsVar, FalseLblName) ->
[DstReg] = create_regs(1),
- Code =
- first_part(BitsVar, DstReg, FalseLblName) ++
- [hipe_rtl:mk_alu(DstReg, DstReg, sll, hipe_rtl:mk_imm(?BYTE_SHIFT))],
+ [FixnumLbl, BignumLbl] = create_lbls(2),
+ WordBits = hipe_rtl_arch:word_size() * ?BYTE_SIZE,
+ FixnumLblName = hipe_rtl:label_name(FixnumLbl),
+ Tail = [BignumLbl,
+ hipe_rtl:mk_branch(DstReg, 'ltu',
+ hipe_rtl:mk_imm(1 bsl (WordBits - ?BYTE_SHIFT)),
+ FixnumLblName, FalseLblName, 0.99),
+ FixnumLbl,
+ hipe_rtl:mk_alu(DstReg, DstReg, sll, hipe_rtl:mk_imm(?BYTE_SHIFT))],
+ Code = first_part(BitsVar, DstReg, FalseLblName, FixnumLblName,
+ hipe_rtl:label_name(BignumLbl), Tail),
{Code, DstReg};
make_size(UnitImm, BitsVar, FalseLblName) ->
[DstReg] = create_regs(1),
@@ -1151,12 +1190,13 @@ floorlog2(X) ->
round(math:log(X)/math:log(2)-0.5).
set_high(X) ->
- set_high(X, 0).
+ WordBits = hipe_rtl_arch:word_size() * ?BYTE_SIZE,
+ set_high(min(X, WordBits), WordBits, 0).
-set_high(0, Y) ->
+set_high(0, _, Y) ->
Y;
-set_high(X, Y) ->
- set_high(X-1, Y+(1 bsl (27-X))).
+set_high(X, WordBits, Y) ->
+ set_high(X-1, WordBits, Y+(1 bsl (WordBits-X))).
is_illegal_const(Const) ->
Const >= 1 bsl (hipe_rtl_arch:word_size() * ?BYTE_SIZE) orelse Const < 0.
diff --git a/lib/hipe/rtl/hipe_tagscheme.erl b/lib/hipe/rtl/hipe_tagscheme.erl
index 1bb4c3cc5f..d77078acb6 100644
--- a/lib/hipe/rtl/hipe_tagscheme.erl
+++ b/lib/hipe/rtl/hipe_tagscheme.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2015. All 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,8 @@
test_any_pid/4, test_any_port/4,
test_ref/4, test_fun/4, test_fun2/5, test_matchstate/4,
test_binary/4, test_bitstr/4, test_list/4, test_map/4,
- test_integer/4, test_number/4, test_tuple_N/5]).
+ test_integer/4, test_number/4, test_tuple_N/5,
+ test_pos_bignum_arity/5]).
-export([realtag_fixnum/2, tag_fixnum/2, realuntag_fixnum/2, untag_fixnum/2]).
-export([test_two_fixnums/3, test_fixnums/4, unsafe_fixnum_add/3,
unsafe_fixnum_sub/3,
@@ -53,9 +54,10 @@
-export([unsafe_closure_element/3]).
-export([mk_fun_header/0, tag_fun/2]).
-export([unsafe_untag_float/2, unsafe_tag_float/2]).
--export([mk_sub_binary/6,mk_sub_binary/7]).
+-export([mk_sub_binary/6, mk_sub_binary/7]).
-export([unsafe_mk_big/3, unsafe_load_float/3]).
--export([bignum_sizeneed/1,bignum_sizeneed_code/2, get_one_word_pos_bignum/3]).
+-export([bignum_sizeneed/1, bignum_sizeneed_code/2, get_one_word_pos_bignum/3,
+ unsafe_get_one_word_pos_bignum/2]).
-export([test_subbinary/3, test_heap_binary/3]).
-export([create_heap_binary/3, create_refc_binary/3, create_refc_binary/4]).
-export([create_matchstate/6, convert_matchstate/1, compare_matchstate/4]).
@@ -349,6 +351,15 @@ test_pos_bignum(X, TrueLab, FalseLab, Pred) ->
mask_and_compare(Tmp, BigMask, ?TAG_HEADER_POS_BIG,
TrueLab, FalseLab, Pred)].
+test_pos_bignum_arity(X, Arity, TrueLab, FalseLab, Pred) ->
+ Tmp = hipe_rtl:mk_new_reg_gcsafe(),
+ HalfTrueLab = hipe_rtl:mk_new_label(),
+ HeaderImm = hipe_rtl:mk_imm(mk_header(Arity, ?TAG_HEADER_POS_BIG)),
+ [test_is_boxed(X, hipe_rtl:label_name(HalfTrueLab), FalseLab, Pred),
+ HalfTrueLab,
+ get_header(Tmp, X),
+ hipe_rtl:mk_branch(Tmp, 'eq', HeaderImm, TrueLab, FalseLab, Pred)].
+
test_matchstate(X, TrueLab, FalseLab, Pred) ->
Tmp = hipe_rtl:mk_new_reg_gcsafe(),
HalfTrueLab = hipe_rtl:mk_new_label(),
@@ -963,13 +974,16 @@ get_one_word_pos_bignum(USize, Size, Fail) ->
Header = hipe_rtl:mk_new_reg(),
HalfLbl = hipe_rtl:mk_new_label(),
HalfLblName = hipe_rtl:label_name(HalfLbl),
- WordSize = hipe_rtl_arch:word_size(),
PosHead = hipe_rtl:mk_imm(mk_header(1, ?TAG_HEADER_POS_BIG)),
[get_header(Header, Size),
hipe_rtl:mk_branch(Header, eq, PosHead, HalfLblName, Fail),
- HalfLbl,
- hipe_rtl:mk_load(USize, Size, hipe_rtl:mk_imm(1*WordSize
- -?TAG_PRIMARY_BOXED))].
+ HalfLbl |
+ unsafe_get_one_word_pos_bignum(USize, Size)].
+
+unsafe_get_one_word_pos_bignum(USize, Size) ->
+ WordSize = hipe_rtl_arch:word_size(),
+ Imm = hipe_rtl:mk_imm(1*WordSize-?TAG_PRIMARY_BOXED),
+ [hipe_rtl:mk_load(USize, Size, Imm)].
-spec bignum_sizeneed(non_neg_integer()) -> non_neg_integer().
diff --git a/lib/hipe/test/bs_SUITE_data/bs_match.erl b/lib/hipe/test/bs_SUITE_data/bs_match.erl
index 7bc93a316b..b241ea8d35 100644
--- a/lib/hipe/test/bs_SUITE_data/bs_match.erl
+++ b/lib/hipe/test/bs_SUITE_data/bs_match.erl
@@ -1,8 +1,8 @@
%%% -*- erlang-indent-level: 2 -*-
%%%-------------------------------------------------------------------
%%% File : bs_match.erl
-%%% Author : Per Gustafsson <[email protected]>
-%%% Purpose : Performs simple matching and construction of binaries
+%%% Authors : Per Gustafsson <[email protected]>, Kostis Sagonas <[email protected]>
+%%% Purpose : Tests matching and construction of binaries
%%% TODO : Add binary and float tests
%%% Created : 20 Feb 2004
%%%-------------------------------------------------------------------
@@ -13,7 +13,7 @@
test() ->
Funs = [fun test_aligned/0, fun test_unaligned/0,
fun test_zero_tail/0, fun test_integer_matching/0,
- fun test_writable_bin/0],
+ fun test_writable_bin/0, fun test_match_huge_bin/0],
lists:foreach(fun (F) -> ok = F() end, Funs).
%%-------------------------------------------------------------------
@@ -175,6 +175,9 @@ test_dynamic_integer_matching(N) ->
<<12:N/integer-little, 0:S>> = <<12:N/integer-little, 0:S>>,
ok.
+%%-------------------------------------------------------------------
+%% Test writable bin -- added by Sverker Eriksson
+
test_writable_bin() ->
test_writable_bin(<<>>, 0),
ok.
@@ -185,3 +188,102 @@ test_writable_bin(Bin0, N) when N < 128 ->
Bin1 = <<Bin0/binary, N>>,
<<_/utf8, _/binary>> = Bin1,
test_writable_bin(Bin1, N+1).
+
+%%-------------------------------------------------------------------
+%% Test matching with a huge bin -- taken from bs_match_bin_SUITE
+
+test_match_huge_bin() ->
+ Bin = <<0:(1 bsl 27),13:8>>,
+ skip_huge_bin_1(1 bsl 27, Bin),
+ 16777216 = match_huge_bin_1(1 bsl 27, Bin),
+ %% Test overflowing the size of a binary field.
+ nomatch = overflow_huge_bin_skip_32(Bin),
+ nomatch = overflow_huge_bin_32(Bin),
+ nomatch = overflow_huge_bin_skip_64(Bin),
+ nomatch = overflow_huge_bin_64(Bin),
+ %% Size in variable
+ ok = overflow_huge_bin(Bin, lists:seq(25, 32)++lists:seq(50, 64)),
+ ok = overflow_huge_bin_unit128(Bin, lists:seq(25, 32)++lists:seq(50, 64)),
+ ok.
+
+overflow_huge_bin(Bin, [Sz0|Sizes]) ->
+ Sz = id(1 bsl Sz0),
+ case Bin of
+ <<_:Sz/binary-unit:8,0,_/binary>> ->
+ {error,Sz};
+ _ ->
+ case Bin of
+ <<NewBin:Sz/binary-unit:8,0,_/binary>> ->
+ {error,Sz,size(NewBin)};
+ _ ->
+ overflow_huge_bin(Bin, Sizes)
+ end
+ end;
+overflow_huge_bin(_, []) -> ok.
+
+overflow_huge_bin_unit128(Bin, [Sz0|Sizes]) ->
+ Sz = id(1 bsl Sz0),
+ case Bin of
+ <<_:Sz/binary-unit:128,0,_/binary>> ->
+ {error,Sz};
+ _ ->
+ case Bin of
+ <<NewBin:Sz/binary-unit:128,0,_/binary>> ->
+ {error,Sz,size(NewBin)};
+ _ ->
+ overflow_huge_bin_unit128(Bin, Sizes)
+ end
+ end;
+overflow_huge_bin_unit128(_, []) -> ok.
+
+skip_huge_bin_1(I, Bin) ->
+ <<_:I/binary-unit:1,13>> = Bin,
+ ok.
+
+match_huge_bin_1(I, Bin) ->
+ case Bin of
+ <<Val:I/binary-unit:1,13>> -> size(Val);
+ _ -> nomatch
+ end.
+
+overflow_huge_bin_skip_32(<<_:4294967296/binary,0,_/binary>>) -> 1; % 1 bsl 32
+overflow_huge_bin_skip_32(<<_:33554432/binary-unit:128,0,_/binary>>) -> 2; % 1 bsl 25
+overflow_huge_bin_skip_32(<<_:67108864/binary-unit:64,0,_/binary>>) -> 3; % 1 bsl 26
+overflow_huge_bin_skip_32(<<_:134217728/binary-unit:32,0,_/binary>>) -> 4; % 1 bsl 27
+overflow_huge_bin_skip_32(<<_:268435456/binary-unit:16,0,_/binary>>) -> 5; % 1 bsl 28
+overflow_huge_bin_skip_32(<<_:536870912/binary-unit:8,0,_/binary>>) -> 6; % 1 bsl 29
+overflow_huge_bin_skip_32(<<_:1073741824/binary-unit:8,0,_/binary>>) -> 7; % 1 bsl 30
+overflow_huge_bin_skip_32(<<_:2147483648/binary-unit:8,0,_/binary>>) -> 8; % 1 bsl 31
+overflow_huge_bin_skip_32(_) -> nomatch.
+
+overflow_huge_bin_32(<<Bin:4294967296/binary,_/binary>>) -> {1,Bin}; % 1 bsl 32
+overflow_huge_bin_32(<<Bin:33554432/binary-unit:128,0,_/binary>>) -> {2,Bin}; % 1 bsl 25
+overflow_huge_bin_32(<<Bin:67108864/binary-unit:128,0,_/binary>>) -> {3,Bin}; % 1 bsl 26
+overflow_huge_bin_32(<<Bin:134217728/binary-unit:128,0,_/binary>>) -> {4,Bin}; % 1 bsl 27
+overflow_huge_bin_32(<<Bin:268435456/binary-unit:128,0,_/binary>>) -> {5,Bin}; % 1 bsl 28
+overflow_huge_bin_32(<<Bin:536870912/binary-unit:128,0,_/binary>>) -> {6,Bin}; % 1 bsl 29
+overflow_huge_bin_32(<<Bin:1073741824/binary-unit:128,0,_/binary>>) -> {7,Bin}; % 1 bsl 30
+overflow_huge_bin_32(<<Bin:2147483648/binary-unit:128,0,_/binary>>) -> {8,Bin}; % 1 bsl 31
+overflow_huge_bin_32(_) -> nomatch.
+
+overflow_huge_bin_skip_64(<<_:18446744073709551616/binary,0,_/binary>>) -> 1; % 1 bsl 64
+overflow_huge_bin_skip_64(<<_:144115188075855872/binary-unit:128,0,_/binary>>) -> 2; % 1 bsl 57
+overflow_huge_bin_skip_64(<<_:288230376151711744/binary-unit:64,0,_/binary>>) -> 3; % 1 bsl 58
+overflow_huge_bin_skip_64(<<_:576460752303423488/binary-unit:32,0,_/binary>>) -> 4; % 1 bsl 59
+overflow_huge_bin_skip_64(<<_:1152921504606846976/binary-unit:16,0,_/binary>>) -> 5; % 1 bsl 60
+overflow_huge_bin_skip_64(<<_:2305843009213693952/binary-unit:8,0,_/binary>>) -> 6; % 1 bsl 61
+overflow_huge_bin_skip_64(<<_:4611686018427387904/binary-unit:8,0,_/binary>>) -> 7; % 1 bsl 62
+overflow_huge_bin_skip_64(<<_:9223372036854775808/binary-unit:8,_/binary>>) -> 8; % 1 bsl 63
+overflow_huge_bin_skip_64(_) -> nomatch.
+
+overflow_huge_bin_64(<<Bin:18446744073709551616/binary,_/binary>>) -> {1,Bin}; % 1 bsl 64
+overflow_huge_bin_64(<<Bin:144115188075855872/binary-unit:128,0,_/binary>>) -> {2,Bin}; % 1 bsl 57
+overflow_huge_bin_64(<<Bin:288230376151711744/binary-unit:128,0,_/binary>>) -> {3,Bin}; % 1 bsl 58
+overflow_huge_bin_64(<<Bin:576460752303423488/binary-unit:128,0,_/binary>>) -> {4,Bin}; % 1 bsl 59
+overflow_huge_bin_64(<<Bin:1152921504606846976/binary-unit:128,0,_/binary>>) -> {5,Bin}; % 1 bsl 60
+overflow_huge_bin_64(<<Bin:2305843009213693952/binary-unit:128,0,_/binary>>) -> {6,Bin}; % 1 bsl 61
+overflow_huge_bin_64(<<Bin:4611686018427387904/binary-unit:128,0,_/binary>>) -> {7,Bin}; % 1 bsl 62
+overflow_huge_bin_64(<<Bin:9223372036854775808/binary-unit:128,0,_/binary>>) -> {8,Bin}; % 1 bsl 63
+overflow_huge_bin_64(_) -> nomatch.
+
+id(I) -> I.
diff --git a/lib/inets/doc/src/http_server.xml b/lib/inets/doc/src/http_server.xml
index 4b6d64fc8f..aeda961714 100644
--- a/lib/inets/doc/src/http_server.xml
+++ b/lib/inets/doc/src/http_server.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2013</year>
+ <year>2004</year><year>2015</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -21,18 +21,8 @@
limitations under the License.
</legalnotice>
-
<title>HTTP server</title>
- <prepared>Ingela Anderton Andin</prepared>
- <responsible></responsible>
- <docno></docno>
- <approved></approved>
- <checked></checked>
- <date></date>
- <rev></rev>
<file>http_server.xml</file>
-
- <marker id="intro"></marker>
</header>
<section>
@@ -65,12 +55,9 @@
<p>As of <c>Inets</c> 5.0 the HTTP server is an easy to
start/stop and customize web server providing the most basic
- web server functionality. Depending on your needs, there
- are also other Erlang-based web servers that can be of interest
- such as <url href=" http://yaws.hyber.org ">Yaws</url>, which,
- for example, has its own
- markup support to generate HTML and supports certain buzzword
- technologies, such as SOAP.</p>
+ web server functionality. Inets is designed for embedded systems
+ and if you want a full-fledged web server there are exists other
+ erlang open source alternatives.</p>
<p>Almost all server functionality has been implemented using an
especially crafted server API, which is described in the Erlang Web
@@ -356,9 +343,9 @@ UserName:Password</pre>
</taglist>
<section>
- <title>CGI Version 1.1,
- <url href="http://www.ietf.org/rfc/rfc3875.txt">RFC 3875</url></title>
- <p>The module <c>mod_cgi</c> enables execution of CGI scripts
+ <title>CGI Version 1.1, RFC 3875</title>
+ <p>The module <c>mod_cgi</c> enables execution of
+ <url href="http://www.ietf.org/rfc/rfc3875.txt">CGI scripts</url>
on the server. A file matching the definition of a
ScriptAlias config directive is treated as a CGI script. A CGI
script is executed by the server and its output is returned to
@@ -541,7 +528,7 @@ http://your.server.org/eval?httpd_example:print(atom_to_list(apply(erlang,halt,[
<title>mod_action - Filetype/Method-Based Script Execution</title>
<p>This module runs CGI scripts whenever a file of a
certain type or HTTP method (see
- <url href="http://tools.ietf.org/html/rfc1945">RFC 1945</url>RFC 1945)
+ <url href="http://tools.ietf.org/html/rfc1945">RFC 1945</url>)
is requested.
</p>
<p>Uses the following Erlang Web Server API interaction data:
@@ -568,7 +555,7 @@ http://your.server.org/eval?httpd_example:print(atom_to_list(apply(erlang,halt,[
<taglist>
<tag><c>{real_name, PathData}</c></tag>
<item><c>PathData</c> is the argument used for API function
- <seealso marker="mod_alias:path/3">mod_alias:path/3</seealso>.</item>
+ <seealso marker="mod_alias#path/3">mod_alias:path/3</seealso>.</item>
</taglist>
</section>
diff --git a/lib/inets/doc/src/http_uri.xml b/lib/inets/doc/src/http_uri.xml
index 64e6c7a6cc..8e0301c520 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>2013</year>
+ <year>2012</year><year>2015</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -142,14 +142,14 @@
<p>If the fragment option is <c>true</c>, the URI fragment is returned as
part of the parsing result, otherwise it is ignored.</p>
- <p>Scheme validation fun is to be defined as follows:
+ <p>Scheme validation fun is to be defined as follows:</p>
- <code>
+ <code>
fun(SchemeStr :: string()) ->
valid | {error, Reason :: term()}.
- </code>
+ </code>
- It is called before scheme string gets converted into scheme atom and
+ <p>It is called before scheme string gets converted into scheme atom and
thus possible atom leak could be prevented</p>
<marker id="encode"></marker>
diff --git a/lib/inets/doc/src/httpc.xml b/lib/inets/doc/src/httpc.xml
index 31e44f405c..ca9b268a03 100644
--- a/lib/inets/doc/src/httpc.xml
+++ b/lib/inets/doc/src/httpc.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2004</year><year>2013</year>
+ <year>2004</year><year>2015</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -554,8 +554,8 @@
<v>IpDesc = string()</v>
<d>Example: "134.138" or "[FEDC:BA98"
(all IP addresses starting with 134.138 or FEDC:BA98),
- "66.35.250.150" or "[2010:836B:4179::836B:4179]" (a complete IP address).</d>
- <d><c>proxy</c> defaults to <c>{undefined, []}</c>,
+ "66.35.250.150" or "[2010:836B:4179::836B:4179]" (a complete IP address).
+ <c>proxy</c> defaults to <c>{undefined, []}</c>,
that is, no proxy is configured and
<c>https_proxy</c> defaults to the value of <c>proxy</c>.</d>
<v>MaxSessions = integer()</v>
@@ -597,8 +597,8 @@
for details.</d>
<v>socket_opts() = [socket_opt()]</v>
<d>The options are appended to the socket options used by the
- client.</d>
- <d>These are the default values when a new request handler
+ client.
+ These are the default values when a new request handler
is started (for the initial connect). They are passed directly
to the underlying transport (<c>gen_tcp</c> or <c>SSL</c>)
<em>without</em> verification.</d>
diff --git a/lib/inets/doc/src/httpd.xml b/lib/inets/doc/src/httpd.xml
index 2a4aea41c2..62b92b8356 100644
--- a/lib/inets/doc/src/httpd.xml
+++ b/lib/inets/doc/src/httpd.xml
@@ -30,13 +30,14 @@
<file>httpd.sgml</file>
</header>
<module>httpd</module>
- <modulesummary>An implementation of an HTTP
- 1.1 compliant web server, as defined in <url href="http://www.ietf.org/rfc/rfc2616.txt">RFC 2616</url>
+ <modulesummary>
+ HTTP server API
</modulesummary>
<description>
- <p>This module provides the HTTP server start options, some administrative
- functions, and specifies the Erlang web server callback
- API.</p>
+ <p>An implementation of an HTTP 1.1 compliant web server, as defined in
+ <url href="http://www.ietf.org/rfc/rfc2616.txt">RFC 2616</url>.
+ Provides web server start options, administrative functions, and
+ an Erlang callback API.</p>
</description>
<section>
@@ -78,8 +79,7 @@
list.</p>
<taglist>
- <marker id="prop_proplist_file"></marker>
- <tag>{proplist_file, path()}</tag>
+ <tag><marker id="prop_proplist_file"></marker>{proplist_file, path()}</tag>
<item>
<p>If this property is defined, <c>Inets</c> expects to find
all other properties defined in this file. The
@@ -87,8 +87,7 @@
properties.</p>
</item>
- <marker id="prop_file"></marker>
- <tag>{file, path()}</tag>
+ <tag><marker id="prop_file"></marker>{file, path()}</tag>
<item>
<p>If this property is defined, <c>Inets</c> expects to find all
other properties defined in this file, which uses Apache-like
@@ -121,8 +120,7 @@
<marker id="props_mand"></marker>
<p><em>Mandatory Properties</em></p>
<taglist>
- <marker id="prop_port"></marker>
- <tag>{port, integer()} </tag>
+ <tag><marker id="prop_port"></marker>{port, integer()} </tag>
<item>
<p>The port that the HTTP server listen to.
If zero is specified as port, an arbitrary available port
@@ -130,22 +128,19 @@
determine which port was picked.</p>
</item>
- <marker id="prop_server_name"></marker>
- <tag>{server_name, string()}</tag>
+ <tag><marker id="prop_server_name"></marker>{server_name, string()}</tag>
<item>
<p>The name of your server, normally a fully qualified domain name.</p>
</item>
- <marker id="prop_server_root"></marker>
- <tag>{server_root, path()}</tag>
+ <tag><marker id="prop_server_root"></marker>{server_root, path()}</tag>
<item>
<p>Defines the home directory of the server, where log files, and so on,
can be stored. Relative paths specified in other properties refer
to this directory.</p>
</item>
- <marker id="prop_doc_root"></marker>
- <tag>{document_root, path()}</tag>
+ <tag> <marker id="prop_doc_root"></marker>{document_root, path()}</tag>
<item>
<p>Defines the top directory for the documents that
are available on the HTTP server.</p>
@@ -155,15 +150,13 @@
<marker id="props_comm"></marker>
<p><em>Communication Properties</em></p>
<taglist>
- <marker id="prop_bind_address"></marker>
- <tag>{bind_address, ip_address() | hostname() | any}</tag>
+ <tag><marker id="prop_bind_address"></marker>{bind_address, ip_address() | hostname() | any}</tag>
<item>
<p>Default is <c>any</c>. <c>any</c> is denoted <em>*</em>
in the Apache-like configuration file.</p>
</item>
- <marker id="profile"></marker>
- <tag>{profile, atom()}</tag>
+ <tag><marker id="profile"></marker>{profile, atom()}</tag>
<item>
<p>Used together with <seealso marker="#prop_bind_address"><c>bind_address</c></seealso>
and <seealso marker="#prop_port"><c>port</c></seealso> to uniquely identify
@@ -176,25 +169,23 @@
</p>
</item>
- <marker id="prop_socket_type"></marker>
- <tag>{socket_type, ip_comm | {essl, Config::proplist()}}</tag>
+ <tag><marker id="prop_socket_type"></marker>{socket_type, ip_comm | {ip_comm, Config::proplist()} | {essl, Config::proplist()}}</tag>
<item>
+ <p>For <c>ip_comm</c> configuration options, see
+ <seealso marker="kernel:gen_tcp#listen-2">gen_tcp:listen/2</seealso>, some options
+ that are used internally by httpd can not be set.</p>
<p>For <c>SSL</c> configuration options, see
<seealso marker="ssl:ssl#listen-2">ssl:listen/2</seealso>.</p>
<p>Default is <c>ip_comm</c>.</p>
</item>
- <marker id="prop_ipfamily"></marker>
- <tag>{ipfamily, inet | inet6 | inet6fb4}</tag>
+ <tag><marker id="prop_ipfamily"></marker>{ipfamily, inet | inet6}</tag>
<item>
- <p>This option is only used when option
- <c>socket_type</c> has value <c>ip_comm</c>.</p>
- <p>Default is <c>inet6fb4</c>.</p>
+ <p>Default is <c>inet</c>, legacy option <c>inet6fb4</c> no longer makes sense and will be translated
+ to inet.</p>
</item>
-
- <marker id="prop_minimum_bytes_per_second"></marker>
- <tag>{minimum_bytes_per_second, integer()}</tag>
+ <tag><marker id="prop_minimum_bytes_per_second"></marker>{minimum_bytes_per_second, integer()}</tag>
<item>
<p>If given, sets a minimum of bytes per second value for connections.</p>
<p>If the value is unreached, the socket closes for that connection.</p>
@@ -205,8 +196,7 @@
<marker id="props_api_modules"></marker>
<p><em>Erlang Web Server API Modules</em> </p>
<taglist>
- <marker id="prop_modules"></marker>
- <tag>{modules, [atom()]} </tag>
+ <tag><marker id="prop_modules"></marker>{modules, [atom()]} </tag>
<item>
<p>Defines which modules the HTTP server uses when handling
requests. Default is <c>[mod_alias, mod_auth, mod_esi,
@@ -223,60 +213,52 @@
<p><em>Limit properties</em> </p>
<taglist>
- <marker id="prop_customize"></marker>
- <tag>{customize, atom()}</tag>
+ <tag><marker id="prop_customize"></marker>{customize, atom()}</tag>
<item>
<p>A callback module to customize the inets HTTP servers behaviour
see <seealso marker="httpd_custom_api"> httpd_custom_api</seealso> </p>
</item>
- <marker id="prop_disable_chunked_encoding"></marker>
- <tag>{disable_chunked_transfer_encoding_send, boolean()}</tag>
+ <tag><marker id="prop_disable_chunked_encoding"></marker>{disable_chunked_transfer_encoding_send, boolean()}</tag>
<item>
<p>Allows you to disable chunked
transfer-encoding when sending a response to an HTTP/1.1
client. Default is <c>false</c>.</p>
</item>
- <marker id="prop_keep_alive"></marker>
- <tag>{keep_alive, boolean()}</tag>
+ <tag><marker id="prop_keep_alive"></marker>{keep_alive, boolean()}</tag>
<item>
<p>Instructs the server whether to use persistent
connections when the client claims to be HTTP/1.1
compliant. Default is <c>true</c>.</p>
</item>
- <marker id="prop_keep_alive_timeout"></marker>
- <tag>{keep_alive_timeout, integer()}</tag>
+ <tag><marker id="prop_keep_alive_timeout"></marker>{keep_alive_timeout, integer()}</tag>
<item>
<p>The number of seconds the server waits for a
subsequent request from the client before closing the
connection. Default is <c>150</c>.</p>
</item>
- <marker id="prop_max_body_size"></marker>
- <tag>{max_body_size, integer()}</tag>
+ <tag><marker id="prop_max_body_size"></marker>{max_body_size, integer()}</tag>
<item>
<p>Limits the size of the message body of an HTTP request.
Default is no limit.</p>
</item>
- <marker id="prop_max_clients"></marker>
- <tag>{max_clients, integer()}</tag>
+ <tag><marker id="prop_max_clients"></marker>{max_clients, integer()}</tag>
<item>
<p>Limits the number of simultaneous requests that can be
supported. Default is <c>150</c>.</p>
</item>
- <marker id="prop_max_header_size"></marker>
- <tag>{max_header_size, integer()}</tag>
+ <tag><marker id="prop_max_header_size"></marker>{max_header_size, integer()}</tag>
<item>
<p>Limits the size of the message header of an HTTP request.
Default is <c>10240</c>.</p>
</item>
- <marker id="prop_max_content_length"></marker>
- <tag>{max_content_length, integer()}</tag>
+ <tag><marker id="prop_max_content_length"></marker>{max_content_length, integer()}</tag>
<item>
<p>Maximum content-length in an incoming request, in bytes. Requests
with content larger than this are answered with status 413.
@@ -284,15 +266,13 @@
</p>
</item>
- <marker id="prop_max_uri"></marker>
- <tag>{max_uri_size, integer()}</tag>
+ <tag><marker id="prop_max_uri"></marker>{max_uri_size, integer()}</tag>
<item>
<p>Limits the size of the HTTP request URI.
Default is no limit.</p>
</item>
- <marker id="prop_max_keep_alive_req"></marker>
- <tag>{max_keep_alive_request, integer()}</tag>
+ <tag><marker id="prop_max_keep_alive_req"></marker>{max_keep_alive_request, integer()}</tag>
<item>
<p>The number of requests that a client can do on one
connection. When the server has responded to the number of
@@ -305,8 +285,7 @@
<marker id="props_admin"></marker>
<p><em>Administrative Properties</em></p>
<taglist>
- <marker id="prop_mime_types"></marker>
- <tag>{mime_types, [{MimeType, Extension}] | path()}</tag>
+ <tag><marker id="prop_mime_types"></marker>{mime_types, [{MimeType, Extension}] | path()}</tag>
<item>
<p><c>MimeType = string()</c> and <c>Extension = string()</c>.
Files delivered to the client are MIME typed according to RFC
@@ -322,24 +301,21 @@ text/plain asc txt</pre>
<p>Default is [{"html","text/html"},{"htm","text/html"}].</p>
</item>
- <marker id="prop_mime_type"></marker>
- <tag>{mime_type, string()}</tag>
+ <tag><marker id="prop_mime_type"></marker>{mime_type, string()}</tag>
<item>
<p>When the server is asked to provide a document type that
cannot be determined by the MIME Type Settings, the server
uses this default type.</p>
</item>
- <marker id="prop_server_admin"></marker>
- <tag>{server_admin, string()}</tag>
+ <tag><marker id="prop_server_admin"></marker>{server_admin, string()}</tag>
<item>
<p>Defines the email-address of the server
administrator to be included in any error messages returned by
the server.</p>
</item>
- <marker id="prop_server_tokens"></marker>
- <tag>{server_tokens, none|prod|major|minor|minimal|os|full|{private, string()}}</tag>
+ <tag><marker id="prop_server_tokens"></marker>{server_tokens, none|prod|major|minor|minimal|os|full|{private, string()}}</tag>
<item>
<p>Defines the look of the value of the server header.</p>
<p>Example: Assuming the version of <c>Inets</c> is 5.8.1,
@@ -366,8 +342,7 @@ text/plain asc txt</pre>
<p>By default, the value is as before, that is, <c>minimal</c>.</p>
</item>
- <marker id="prop_log_format"></marker>
- <tag>{log_format, common | combined}</tag>
+ <tag><marker id="prop_log_format"></marker>{log_format, common | combined}</tag>
<item>
<p>Defines if access logs are to be written according to the <c>common</c>
log format or the extended common log format.
@@ -410,8 +385,7 @@ text/plain asc txt</pre>
</p>
</item>
- <marker id="prop_elog_format"></marker>
- <tag>{error_log_format, pretty | compact}</tag>
+ <tag><marker id="prop_elog_format"></marker>{error_log_format, pretty | compact}</tag>
<item>
<p>Default is <c>pretty</c>. If the error log is meant to be read
directly by a human, <c>pretty</c> is the best option.</p>
@@ -433,60 +407,57 @@ text/plain asc txt</pre>
<marker id="props_alias"></marker>
<p><em>URL Aliasing Properties - Requires mod_alias</em></p>
<taglist>
- <marker id="prop_alias"></marker>
- <tag>{alias, {Alias, RealName}}</tag>
+ <tag><marker id="prop_alias"></marker>{alias, {Alias, RealName}}</tag>
<item>
<p><c>Alias = string()</c> and <c>RealName = string()</c>.
<c>alias</c> allows documents to be stored in the local file
system instead of the <c>document_root</c> location. URLs with a path
beginning with url-path is mapped to local files beginning with
- directory-filename, for example:
+ directory-filename, for example:</p>
<code>{alias, {"/image", "/ftp/pub/image"}}</code>
- Access to http://your.server.org/image/foo.gif would refer to
+ <p>Access to http://your.server.org/image/foo.gif would refer to
the file /ftp/pub/image/foo.gif.</p>
</item>
- <marker id="prop_re_write"></marker>
- <tag>{re_write, {Re, Replacement}}</tag>
+ <tag><marker id="prop_re_write"></marker>{re_write, {Re, Replacement}}</tag>
<item>
<p><c>Re = string()</c> and <c>Replacement = string()</c>.
<c>re_write</c> allows documents to be stored in the local file
system instead of the <c>document_root</c> location. URLs are rewritten
by <c>re:replace/3</c> to produce a path in the local file-system,
- for example:
+ for example:</p>
<code>{re_write, {"^/[~]([^/]+)(.*)$", "/home/\\1/public\\2"}}</code>
- Access to http://your.server.org/~bob/foo.gif would refer to
+ <p>Access to http://your.server.org/~bob/foo.gif would refer to
the file /home/bob/public/foo.gif.
In an Apache-like configuration file, <c>Re</c> is separated
from <c>Replacement</c> with one single space, and as expected
backslashes do not need to be backslash escaped, the
- same example would become:
+ same example would become:</p>
<code>ReWrite ^/[~]([^/]+)(.*)$ /home/\1/public\2</code>
- Beware of trailing space in <c>Replacement</c> to be used.
+ <p>Beware of trailing space in <c>Replacement</c> to be used.
If you must have a space in <c>Re</c>, use, for example, the character
encoding <c>\040</c>, see
<seealso marker="stdlib:re">re(3)</seealso>.</p>
</item>
- <marker id="prop_dir_idx"></marker>
- <tag>{directory_index, [string()]}</tag>
+ <tag><marker id="prop_dir_idx"></marker>{directory_index, [string()]}</tag>
<item>
<p><c>directory_index</c> specifies a list of resources to look for
if a client requests a directory using a <c>/</c> at the end of the
directory name. <c>file</c> depicts the name of a file in the
directory. Several files can be given, in which case the server
- returns the first it finds, for example:
+ returns the first it finds, for example:</p>
<code>{directory_index, ["index.hml", "welcome.html"]}</code>
- Access to http://your.server.org/docs/ would return
+ <p>Access to http://your.server.org/docs/ would return
http://your.server.org/docs/index.html or
http://your.server.org/docs/welcome.html if index.html does not
exist.</p>
@@ -496,38 +467,35 @@ text/plain asc txt</pre>
<marker id="props_cgi"></marker>
<p><em>CGI Properties - Requires mod_cgi</em></p>
<taglist>
- <marker id="prop_script_alias"></marker>
- <tag>{script_alias, {Alias, RealName}}</tag>
+ <tag><marker id="prop_script_alias"></marker>{script_alias, {Alias, RealName}}</tag>
<item>
<p><c>Alias = string()</c> and <c>RealName = string()</c>.
Have the same behavior as property <c>alias</c>, except that
they also mark the target directory as containing CGI
scripts. URLs with a path beginning with url-path are mapped to
- scripts beginning with directory-filename, for example:
+ scripts beginning with directory-filename, for example:</p>
<code>{script_alias, {"/cgi-bin/", "/web/cgi-bin/"}}</code>
- Access to http://your.server.org/cgi-bin/foo would cause
+ <p>Access to http://your.server.org/cgi-bin/foo would cause
the server to run the script /web/cgi-bin/foo.</p>
</item>
- <marker id="prop_script_re_write"></marker>
- <tag>{script_re_write, {Re, Replacement}}</tag>
+ <tag><marker id="prop_script_re_write"></marker>{script_re_write, {Re, Replacement}}</tag>
<item>
<p><c>Re = string()</c> and <c>Replacement = string()</c>.
Have the same behavior as property <c>re_write</c>, except that
they also mark the target directory as containing CGI
scripts. URLs with a path beginning with url-path are mapped to
- scripts beginning with directory-filename, for example:
+ scripts beginning with directory-filename, for example:</p>
<code>{script_re_write, {"^/cgi-bin/(\\d+)/", "/web/\\1/cgi-bin/"}}</code>
- Access to http://your.server.org/cgi-bin/17/foo would cause
+ <p>Access to http://your.server.org/cgi-bin/17/foo would cause
the server to run the script /web/17/cgi-bin/foo.</p>
</item>
- <marker id="prop_script_nocache"></marker>
- <tag>{script_nocache, boolean()}</tag>
+ <tag><marker id="prop_script_nocache"></marker>{script_nocache, boolean()}</tag>
<item>
<p>If <c>script_nocache</c> is set to <c>true</c>, the HTTP server by
default adds the header fields necessary to prevent proxies from
@@ -535,8 +503,7 @@ text/plain asc txt</pre>
Default to <c>false</c>.</p>
</item>
- <marker id="prop_script_timeout"></marker>
- <tag>{script_timeout, integer()}</tag>
+ <tag><marker id="prop_script_timeout"></marker>{script_timeout, integer()}</tag>
<item>
<p>The time in seconds the web server waits between each
chunk of data from the script. If the CGI script does not deliver
@@ -544,8 +511,7 @@ text/plain asc txt</pre>
closed. Default is <c>15</c>.</p>
</item>
- <marker id="prop_action"></marker>
- <tag>{action, {MimeType, CgiScript}} - requires mod_action</tag>
+ <tag><marker id="prop_action"></marker>{action, {MimeType, CgiScript}} - requires mod_action</tag>
<item>
<p><c>MimeType = string()</c> and <c>CgiScript = string()</c>.
<c>action</c> adds an action activating a CGI script
@@ -558,8 +524,7 @@ text/plain asc txt</pre>
<code>{action, {"text/plain", "/cgi-bin/log_and_deliver_text"}}</code>
</item>
- <marker id="prop_script"></marker>
- <tag>{script, {Method, CgiScript}} - requires mod_action</tag>
+ <tag><marker id="prop_script"></marker>{script, {Method, CgiScript}} - requires mod_action</tag>
<item>
<p><c>Method = string()</c> and <c>CgiScript = string()</c>.
<c>script</c> adds an action activating a CGI script
@@ -578,17 +543,16 @@ text/plain asc txt</pre>
<marker id="props_esi"></marker>
<p><em>ESI Properties - Requires mod_esi</em></p>
<taglist>
- <marker id="prop_esi_alias"></marker>
- <tag>{erl_script_alias, {URLPath, [AllowedModule]}}</tag>
+ <tag><marker id="prop_esi_alias"></marker>{erl_script_alias, {URLPath, [AllowedModule]}}</tag>
<item>
<p><c>URLPath = string()</c> and <c>AllowedModule = atom()</c>.
<c>erl_script_alias</c> marks all URLs matching url-path as erl
scheme scripts. A matching URL is mapped into a specific module
- and function, for example:
+ and function, for example:</p>
<code>{erl_script_alias, {"/cgi-bin/example", [httpd_example]}}</code>
- A request to
+ <p>A request to
http://your.server.org/cgi-bin/example/httpd_example:yahoo
would refer to httpd_example:yahoo/3 or, if that does not exist,
httpd_example:yahoo/2 and
@@ -596,8 +560,7 @@ text/plain asc txt</pre>
not be allowed to execute.</p>
</item>
- <marker id="prop_esi_nocache"></marker>
- <tag>{erl_script_nocache, boolean()}</tag>
+ <tag><marker id="prop_esi_nocache"></marker>{erl_script_nocache, boolean()}</tag>
<item>
<p>If <c>erl_script_nocache</c> is set to <c>true</c>, the server adds
HTTP header fields preventing proxies from caching the
@@ -606,8 +569,7 @@ text/plain asc txt</pre>
Default is <c>false</c>.</p>
</item>
- <marker id="prop_esi_timeout"></marker>
- <tag>{erl_script_timeout, integer()}</tag>
+ <tag><marker id="prop_esi_timeout"></marker>{erl_script_timeout, integer()}</tag>
<item>
<p>If <c>erl_script_timeout</c> sets the time in seconds the server
waits between each chunk of data to be delivered through
@@ -615,8 +577,7 @@ text/plain asc txt</pre>
for scripts that use the erl scheme.</p>
</item>
- <marker id="prop_esi_timeout"></marker>
- <tag>{eval_script_alias, {URLPath, [AllowedModule]}}</tag>
+ <tag><marker id="prop_esi_timeout"></marker>{eval_script_alias, {URLPath, [AllowedModule]}}</tag>
<item>
<p><c>URLPath = string()</c> and <c>AllowedModule = atom()</c>.
Same as <c>erl_script_alias</c> but for scripts
@@ -628,24 +589,21 @@ text/plain asc txt</pre>
<marker id="props_log"></marker>
<p><em>Log Properties - Requires mod_log</em></p>
<taglist>
- <marker id="prop_elog"></marker>
- <tag>{error_log, path()}</tag>
+ <tag><marker id="prop_elog"></marker>{error_log, path()}</tag>
<item>
<p>Defines the filename of the error log file to be used to log
server errors. If the filename does not begin with a slash (/),
it is assumed to be relative to the <c>server_root</c>.</p>
</item>
- <marker id="prop_slog"></marker>
- <tag>{security_log, path()}</tag>
+ <tag><marker id="prop_slog"></marker>{security_log, path()}</tag>
<item>
<p>Defines the filename of the access log file to be used to
log security events. If the filename does not begin with a slash
(/), it is assumed to be relative to the <c>server_root</c>.</p>
</item>
- <marker id="prop_tlog"></marker>
- <tag>{transfer_log, path()}</tag>
+ <tag><marker id="prop_tlog"></marker>{transfer_log, path()}</tag>
<item>
<p>Defines the filename of the access log file to be used to
log incoming requests. If the filename does not begin with a
@@ -656,8 +614,7 @@ text/plain asc txt</pre>
<marker id="props_dlog"></marker>
<p><em>Disk Log Properties - Requires mod_disk_log</em></p>
<taglist>
- <marker id="prop_dlog_format"></marker>
- <tag>{disk_log_format, internal | external}</tag>
+ <tag><marker id="prop_dlog_format"></marker>{disk_log_format, internal | external}</tag>
<item>
<p>Defines the file format of the log files. See <c>disk_log</c> for
details. If the internal file format is used, the
@@ -667,16 +624,14 @@ text/plain asc txt</pre>
<c>external</c>.</p>
</item>
- <marker id="prop_edlog"></marker>
- <tag>{error_disk_log, path()}</tag>
+ <tag><marker id="prop_edlog"></marker>{error_disk_log, path()}</tag>
<item>
<p>Defines the filename of the (<c>disk_log(3)</c>) error log file
to be used to log server errors. If the filename does not begin
with a slash (/), it is assumed to be relative to the <c>server_root</c>.</p>
</item>
- <marker id="prop_edlog_size"></marker>
- <tag>{error_disk_log_size, {MaxBytes, MaxFiles}}</tag>
+ <tag><marker id="prop_edlog_size"></marker>{error_disk_log_size, {MaxBytes, MaxFiles}}</tag>
<item>
<p><c>MaxBytes = integer()</c> and <c>MaxFiles = integer()</c>.
Defines the properties of the (<c>disk_log(3)</c>) error log
@@ -685,8 +640,7 @@ text/plain asc txt</pre>
used before the first file is truncated and reused.</p>
</item>
- <marker id="prop_sdlog"></marker>
- <tag>{security_disk_log, path()}</tag>
+ <tag><marker id="prop_sdlog"></marker>{security_disk_log, path()}</tag>
<item>
<p>Defines the filename of the (<c>disk_log(3)</c>) access log file
logging incoming security events, that is, authenticated
@@ -694,8 +648,7 @@ text/plain asc txt</pre>
is assumed to be relative to the <c>server_root</c>.</p>
</item>
- <marker id="prop_sdlog_size"></marker>
- <tag>{security_disk_log_size, {MaxBytes, MaxFiles}}</tag>
+ <tag><marker id="prop_sdlog_size"></marker>{security_disk_log_size, {MaxBytes, MaxFiles}}</tag>
<item>
<p><c>MaxBytes = integer()</c> and <c>MaxFiles = integer()</c>.
Defines the properties of the <c>disk_log(3)</c> access log
@@ -704,8 +657,7 @@ text/plain asc txt</pre>
used before the first file is truncated and reused.</p>
</item>
- <marker id="prop_tdlog"></marker>
- <tag>{transfer_disk_log, path()}</tag>
+ <tag><marker id="prop_tdlog"></marker>{transfer_disk_log, path()}</tag>
<item>
<p>Defines the filename of the (<c>disk_log(3)</c>) access log file
logging incoming requests. If the filename does not begin
@@ -713,8 +665,7 @@ text/plain asc txt</pre>
<c>server_root</c>.</p>
</item>
- <marker id="prop_tdlog_size"></marker>
- <tag>{transfer_disk_log_size, {MaxBytes, MaxFiles}}</tag>
+ <tag><marker id="prop_tdlog_size"></marker>{transfer_disk_log_size, {MaxBytes, MaxFiles}}</tag>
<item>
<p><c>MaxBytes = integer()</c> and <c>MaxFiles = integer()</c>.
Defines the properties of the <c>disk_log(3)</c> access log
@@ -734,32 +685,29 @@ text/plain asc txt</pre>
<p>The properties for directories are as follows:</p>
<taglist>
- <marker id="prop_allow_from"></marker>
- <tag>{allow_from, all | [RegxpHostString]}</tag>
+ <tag><marker id="prop_allow_from"></marker>{allow_from, all | [RegxpHostString]}</tag>
<item>
<p>Defines a set of hosts to be granted access to a
- given directory, for example:
+ given directory, for example:</p>
<code>{allow_from, ["123.34.56.11", "150.100.23"]}</code>
- The host <c>123.34.56.11</c> and all machines on the <c>150.100.23</c>
+ <p>The host <c>123.34.56.11</c> and all machines on the <c>150.100.23</c>
subnet are allowed access.</p>
</item>
- <marker id="prop_deny_from"></marker>
- <tag>{deny_from, all | [RegxpHostString]}</tag>
+ <tag><marker id="prop_deny_from"></marker>{deny_from, all | [RegxpHostString]}</tag>
<item>
<p>Defines a set of hosts
- to be denied access to a given directory, for example:
+ to be denied access to a given directory, for example:</p>
<code>{deny_from, ["123.34.56.11", "150.100.23"]}</code>
- The host <c>123.34.56.11</c> and all machines on the <c>150.100.23</c>
+ <p>The host <c>123.34.56.11</c> and all machines on the <c>150.100.23</c>
subnet are not allowed access.</p>
</item>
- <marker id="prop_auth_type"></marker>
- <tag>{auth_type, plain | dets | mnesia}</tag>
+ <tag><marker id="prop_auth_type"></marker>{auth_type, plain | dets | mnesia}</tag>
<item>
<p>Sets the type of authentication database that is used for the
directory. The key difference between the different methods is
@@ -769,8 +717,7 @@ text/plain asc txt</pre>
configuration files.</p>
</item>
- <marker id="prop_auth_user_file"></marker>
- <tag>{auth_user_file, path()}</tag>
+ <tag><marker id="prop_auth_user_file"></marker>{auth_user_file, path()}</tag>
<item>
<p>Sets the name of a file containing the list of users and
passwords for user authentication. The filename can be either
@@ -794,8 +741,7 @@ text/plain asc txt</pre>
clients can download it.</p>
</item>
- <marker id="prop_auth_group_file"></marker>
- <tag>{auth_group_file, path()}</tag>
+ <tag><marker id="prop_auth_group_file"></marker>{auth_group_file, path()}</tag>
<item>
<p>Sets the name of a file containing the list of user
groups for user authentication. The filename can be either
@@ -817,16 +763,14 @@ text/plain asc txt</pre>
can download it.</p>
</item>
- <marker id="prop_auth_name"></marker>
- <tag>{auth_name, string()}</tag>
+ <tag><marker id="prop_auth_name"></marker>{auth_name, string()}</tag>
<item>
<p>Sets the name of the authorization realm (auth-domain) for
a directory. This string informs the client about which
username and password to use.</p>
</item>
- <marker id="prop_auth_access_passwd"></marker>
- <tag>{auth_access_password, string()}</tag>
+ <tag><marker id="prop_auth_access_passwd"></marker>{auth_access_password, string()}</tag>
<item>
<p>If set to other than "NoPassword", the password is required
for all API calls. If the password is set to "DummyPassword", the
@@ -836,15 +780,13 @@ text/plain asc txt</pre>
text in the configuration file.</p>
</item>
- <marker id="prop_req_user"></marker>
- <tag>{require_user, [string()]}</tag>
+ <tag><marker id="prop_req_user"></marker>{require_user, [string()]}</tag>
<item>
<p>Defines users to grant access to a given
directory using a secret password.</p>
</item>
- <marker id="prop_req_grp"></marker>
- <tag>{require_group, [string()]}</tag>
+ <tag><marker id="prop_req_grp"></marker>{require_group, [string()]}</tag>
<item>
<p>Defines users to grant access to a given
directory using a secret password.</p>
@@ -855,8 +797,7 @@ text/plain asc txt</pre>
<marker id="props_htaccess"></marker>
<p><em>Htaccess Authentication Properties - Requires mod_htaccess</em></p>
<taglist>
- <marker id="prop_access_files"></marker>
- <tag>{access_files, [path()]}</tag>
+ <tag><marker id="prop_access_files"></marker>{access_files, [path()]}</tag>
<item>
<p>Specifies the filenames that are used for
access files. When a request comes, every directory in the path
@@ -876,16 +817,14 @@ text/plain asc txt</pre>
<marker id="props_sdir"></marker>
<p>The properties for the security directories are as follows:</p>
<taglist>
- <marker id="prop_data_file"></marker>
- <tag>{data_file, path()}</tag>
+ <tag><marker id="prop_data_file"></marker>{data_file, path()}</tag>
<item>
<p>Name of the security data file. The filename can either be
absolute or relative to the <c>server_root</c>. This file is used to
store persistent data for module <c>mod_security</c>.</p>
</item>
- <marker id="prop_max_retries"></marker>
- <tag>{max_retries, integer()}</tag>
+ <tag><marker id="prop_max_retries"></marker>{max_retries, integer()}</tag>
<item>
<p>Specifies the maximum number of attempts to authenticate a
user before the user is blocked out. If a user
@@ -897,16 +836,14 @@ text/plain asc txt</pre>
Default is <c>3</c>. Can be set to infinity.</p>
</item>
- <marker id="prop_block_time"></marker>
- <tag>{block_time, integer()}</tag>
+ <tag><marker id="prop_block_time"></marker>{block_time, integer()}</tag>
<item>
<p>Specifies the number of minutes a user is blocked. After
this timehas passed, the user automatically regains access.
Default is <c>60</c>.</p>
</item>
- <marker id="prop_fail_exp_time"></marker>
- <tag>{fail_expire_time, integer()}</tag>
+ <tag><marker id="prop_fail_exp_time"></marker>{fail_expire_time, integer()}</tag>
<item>
<p>Specifies the number of minutes a failed user authentication
is remembered. If a user authenticates after this
@@ -915,8 +852,7 @@ text/plain asc txt</pre>
Default is <c>30</c>.</p>
</item>
- <marker id="prop_auth_timeout"></marker>
- <tag>{auth_timeout, integer()}</tag>
+ <tag><marker id="prop_auth_timeout"></marker>{auth_timeout, integer()}</tag>
<item>
Specifies the number of seconds a successful user
authentication is remembered. After this time has passed, the
diff --git a/lib/inets/doc/src/notes.xml b/lib/inets/doc/src/notes.xml
index ef11fdc10c..7ebb3ddffa 100644
--- a/lib/inets/doc/src/notes.xml
+++ b/lib/inets/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2002</year><year>2014</year>
+ <year>2002</year><year>2015</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -33,7 +33,40 @@
<file>notes.xml</file>
</header>
- <section><title>Inets 6.0.2</title>
+ <section><title>Inets 6.0.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved error handling and gracfully termination when an
+ invalid chunked length header is encountered.</p>
+ <p>
+ Own Id: OTP-13061</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Add possibility to set socket options, such as nodelay,
+ for httpd. Also phase out legacy option value inet6bf4
+ for the ipfamily option. This value will be translated to
+ the value inet.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-13062</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Inets 6.0.2</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
@@ -1774,23 +1807,21 @@
<item>
<p>[httpd] - Issues with ESI erl_script_timeout. </p>
- <p>
- <list type="bulleted">
- <item>
- <p>The <c>erl_script_timeout</c> config option is ducumented
- as a number of seconds. But when parsing the config, in the
- new format (not a config file), it was handled as if in
- number of milliseconds. </p>
- </item>
- <item>
- <p>When the erl-script-timeout time was exceeded, the server
- incorrectly marked the answer as sent, thereby leaving
- client hanging (with an incomplete answer).
- This has been changed, so that now the socket will be
- closed. </p>
- </item>
- </list>
- </p>
+ <list type="bulleted">
+ <item>
+ <p>The <c>erl_script_timeout</c> config option is ducumented
+ as a number of seconds. But when parsing the config, in the
+ new format (not a config file), it was handled as if in
+ number of milliseconds. </p>
+ </item>
+ <item>
+ <p>When the erl-script-timeout time was exceeded, the server
+ incorrectly marked the answer as sent, thereby leaving
+ client hanging (with an incomplete answer).
+ This has been changed, so that now the socket will be
+ closed. </p>
+ </item>
+ </list>
<p>Own Id: OTP-8509</p>
</item>
</list>
@@ -1866,20 +1897,19 @@
<item>
<p>[httpc] Several more or less critical fixes:</p>
- <p>
- <list type="bulleted">
- <item>
- <p>Initial call between the httpc manager and request
- handler was synchronous. </p>
- <p>When the manager starts a new request handler,
- this is no longer a synchronous operation. Previously,
- the new request handler made the connection to the
- server and issuing of the first request (the reason
- for starting it) in the gen_server init function.
- If the connection for some reason "took some time",
- the manager hanged, leaving all other activities by
- that manager also hanging. </p>
- </item>
+ <list type="bulleted">
+ <item>
+ <p>Initial call between the httpc manager and request
+ handler was synchronous. </p>
+ <p>When the manager starts a new request handler,
+ this is no longer a synchronous operation. Previously,
+ the new request handler made the connection to the
+ server and issuing of the first request (the reason
+ for starting it) in the gen_server init function.
+ If the connection for some reason "took some time",
+ the manager hanged, leaving all other activities by
+ that manager also hanging. </p>
+ </item>
<!--
<item>
<p>Copying of data between processes</p>
@@ -1890,8 +1920,7 @@
<p>TBD</p>
</item>
-->
- </list>
- </p>
+ </list>
<p>As a side-effect of these changes, some modules was also
renamed, and a new api module,
<seealso marker="httpc">httpc</seealso>, has been introduced
diff --git a/lib/inets/doc/src/tftp.xml b/lib/inets/doc/src/tftp.xml
index 00d9d53376..10398f5088 100644
--- a/lib/inets/doc/src/tftp.xml
+++ b/lib/inets/doc/src/tftp.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2006</year><year>2013</year>
+ <year>2006</year><year>2015</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -216,12 +216,9 @@
five times when the time-out expires.</p>
</item>
</taglist>
-
- <marker id="start1"></marker>
</section>
<funcs>
- <marker id="change_config_daemons"></marker>
<func>
<name>change_config(daemons, Options) -> [{Pid, Result}]</name>
<fsummary>Changes configuration for all daemons.
@@ -234,8 +231,6 @@
</type>
<desc>
<p>Changes configuration for all TFTP daemon processes. </p>
-
- <marker id="change_config_servers"></marker>
</desc>
</func>
@@ -251,8 +246,6 @@
</type>
<desc>
<p>Changes configuration for all TFTP server processes.</p>
-
- <marker id="change_config_pid"></marker>
</desc>
</func>
@@ -268,7 +261,6 @@
</type>
<desc>
<p>Changes configuration for a TFTP daemon, server, or client process.</p>
- <marker id="info_daemons"></marker>
</desc>
</func>
@@ -282,8 +274,6 @@
</type>
<desc>
<p>Returns information about all TFTP daemon processes.</p>
-
- <marker id="info_servers"></marker>
</desc>
</func>
@@ -297,8 +287,6 @@
</type>
<desc>
<p>Returns information about all TFTP server processes. </p>
-
- <marker id="info_pid"></marker>
</desc>
</func>
@@ -341,9 +329,7 @@
the regexps of these and the callback module corresponding to
the first match is used, or an error tuple is returned if no
matching regexp is found.</p>
- </desc>
-
- <marker id="write_file"></marker>
+ </desc>
</func>
<func>
@@ -359,8 +345,6 @@
port. When it receives a request for read or write, it spawns
a temporary server process handling the actual transfer
of the (virtual) file.</p>
-
- <marker id="read_file"></marker>
</desc>
</func>
@@ -393,7 +377,6 @@
matching regexp is found.</p>
</desc>
</func>
-
</funcs>
<section>
diff --git a/lib/inets/src/http_client/httpc_handler.erl b/lib/inets/src/http_client/httpc_handler.erl
index 6e6cc38c06..d1c52dcc78 100644
--- a/lib/inets/src/http_client/httpc_handler.erl
+++ b/lib/inets/src/http_client/httpc_handler.erl
@@ -26,6 +26,7 @@
-include_lib("inets/src/http_lib/http_internal.hrl").
-include("httpc_internal.hrl").
+-define(IS_STREAMED(Code), ((Code =:= 200) orelse (Code =:= 206))).
%%--------------------------------------------------------------------
%% Internal Application API
@@ -163,22 +164,22 @@ info(Pid) ->
%% Request should not be streamed
stream(BodyPart, #request{stream = none} = Request, _) ->
?hcrt("stream - none", []),
- {BodyPart, Request};
+ {false, BodyPart, Request};
%% Stream to caller
stream(BodyPart, #request{stream = Self} = Request, Code)
- when ((Code =:= 200) orelse (Code =:= 206)) andalso
+ when ?IS_STREAMED(Code) andalso
((Self =:= self) orelse (Self =:= {self, once})) ->
?hcrt("stream - self", [{stream, Self}, {code, Code}]),
httpc_response:send(Request#request.from,
{Request#request.id, stream, BodyPart}),
- {<<>>, Request};
+ {true, <<>>, Request};
%% Stream to file
%% This has been moved to start_stream/3
%% We keep this for backward compatibillity...
stream(BodyPart, #request{stream = Filename} = Request, Code)
- when ((Code =:= 200) orelse (Code =:= 206)) andalso is_list(Filename) ->
+ when ?IS_STREAMED(Code) andalso is_list(Filename) ->
?hcrt("stream - filename", [{stream, Filename}, {code, Code}]),
case file:open(Filename, [write, raw, append, delayed_write]) of
{ok, Fd} ->
@@ -190,18 +191,18 @@ stream(BodyPart, #request{stream = Filename} = Request, Code)
%% Stream to file
stream(BodyPart, #request{stream = Fd} = Request, Code)
- when ((Code =:= 200) orelse (Code =:= 206)) ->
+ when ?IS_STREAMED(Code) ->
?hcrt("stream to file", [{stream, Fd}, {code, Code}]),
case file:write(Fd, BodyPart) of
ok ->
- {<<>>, Request};
+ {true, <<>>, Request};
{error, Reason} ->
exit({stream_to_file_failed, Reason})
end;
stream(BodyPart, Request,_) -> % only 200 and 206 responses can be streamed
?hcrt("stream - ignore", [{request, Request}]),
- {BodyPart, Request}.
+ {false, BodyPart, Request}.
%%====================================================================
@@ -474,18 +475,18 @@ handle_info({Proto, _Socket, Data},
{Module, whole_body, [Body, Length]} ->
?hcrd("data processed - whole body", [{length, Length}]),
{_, Code, _} = StatusLine,
- {NewBody, NewRequest} = stream(Body, Request, Code),
+ {Streamed, NewBody, NewRequest} = stream(Body, Request, Code),
%% When we stream we will not keep the already
%% streamed data, that would be a waste of memory.
NewLength =
- case Stream of
- none ->
+ case Streamed of
+ false ->
Length;
- _ ->
+ true ->
Length - size(Body)
end,
- NewState = next_body_chunk(State),
+ NewState = next_body_chunk(State, Code),
NewMFA = {Module, whole_body, [NewBody, NewLength]},
{noreply, NewState#state{mfa = NewMFA,
request = NewRequest}};
@@ -497,8 +498,8 @@ handle_info({Proto, _Socket, Data},
%% The response body is chunk-encoded. Steal decoded
%% chunks as much as possible to stream.
{_, Code, _} = StatusLine,
- {NewBody, NewRequest} = stream(BodySoFar, Request, Code),
- NewState = next_body_chunk(State),
+ {_, NewBody, NewRequest} = stream(BodySoFar, Request, Code),
+ NewState = next_body_chunk(State, Code),
NewMFA = {Module, decode_size,
[TotalChunk, HexList,
{MaxBodySize, NewBody, AccLength, MaxHeaderSize}]},
@@ -517,8 +518,8 @@ handle_info({Proto, _Socket, Data},
NewChunkSize = ChunkSize - ChunkSizeToSteal,
{_, Code, _} = StatusLine,
- {NewBody, NewRequest} = stream(StolenBody, Request, Code),
- NewState = next_body_chunk(State),
+ {_, NewBody, NewRequest} = stream(StolenBody, Request, Code),
+ NewState = next_body_chunk(State, Code),
NewMFA = {Module, decode_data,
[NewChunkSize, NewTotalChunk,
{MaxBodySize, NewBody, AccLength, MaxHeaderSize}]},
@@ -1071,13 +1072,13 @@ handle_http_msg({ChunkedHeaders, Body},
?hcrt("handle_http_msg",
[{chunked_headers, ChunkedHeaders}, {headers, Headers}]),
NewHeaders = http_chunk:handle_headers(Headers, ChunkedHeaders),
- {NewBody, NewRequest} = stream(Body, State#state.request, Code),
+ {_, NewBody, NewRequest} = stream(Body, State#state.request, Code),
handle_response(State#state{headers = NewHeaders,
body = NewBody,
request = NewRequest});
handle_http_msg(Body, #state{status_line = {_,Code, _}} = State) ->
?hcrt("handle_http_msg", [{code, Code}]),
- {NewBody, NewRequest} = stream(Body, State#state.request, Code),
+ {_, NewBody, NewRequest} = stream(Body, State#state.request, Code),
handle_response(State#state{body = NewBody, request = NewRequest}).
handle_http_body(_, #state{status = {ssl_tunnel, _},
@@ -1112,14 +1113,14 @@ handle_http_body(Body, #state{headers = Headers,
case case_insensitive_header(TransferEnc) of
"chunked" ->
?hcrt("handle_http_body - chunked", []),
- case http_chunk:decode(Body, State#state.max_body_size,
- State#state.max_header_size) of
+ try http_chunk:decode(Body, State#state.max_body_size,
+ State#state.max_header_size) of
{Module, Function, Args} ->
?hcrt("handle_http_body - new mfa",
[{module, Module},
{function, Function},
{args, Args}]),
- NewState = next_body_chunk(State),
+ NewState = next_body_chunk(State, Code),
{noreply, NewState#state{mfa =
{Module, Function, Args}}};
{ok, {ChunkedHeaders, NewBody}} ->
@@ -1133,11 +1134,18 @@ handle_http_body(Body, #state{headers = Headers,
handle_response(State#state{headers = NewHeaders,
body = NewBody});
_ ->
- {NewBody2, _NewRequest} =
+ {_, NewBody2, _} =
stream(NewBody, Request, Code),
handle_response(State#state{headers = NewHeaders,
body = NewBody2})
end
+ catch throw:{error, Reason} ->
+ NewState =
+ answer_request(Request,
+ httpc_response:error(Request,
+ Reason),
+ State),
+ {stop, normal, NewState}
end;
Enc when Enc =:= "identity"; Enc =:= undefined ->
?hcrt("handle_http_body - identity", []),
@@ -1147,12 +1155,12 @@ handle_http_body(Body, #state{headers = Headers,
true ->
case httpc_response:whole_body(Body, Length) of
{ok, Body} ->
- {NewBody, NewRequest} =
+ {_, NewBody, NewRequest} =
stream(Body, Request, Code),
handle_response(State#state{body = NewBody,
request = NewRequest});
MFA ->
- NewState = next_body_chunk(State),
+ NewState = next_body_chunk(State, Code),
{noreply, NewState#state{mfa = MFA}}
end;
false ->
@@ -1646,21 +1654,21 @@ start_stream({_Version, _Code, _ReasonPhrase}, _Headers,
{ok, Request};
start_stream({_Version, Code, _ReasonPhrase}, Headers,
#request{stream = self} = Request)
- when (Code =:= 200) orelse (Code =:= 206) ->
+ when ?IS_STREAMED(Code) ->
?hcrt("start stream - self", [{code, Code}]),
Msg = httpc_response:stream_start(Headers, Request, ignore),
httpc_response:send(Request#request.from, Msg),
{ok, Request};
start_stream({_Version, Code, _ReasonPhrase}, Headers,
#request{stream = {self, once}} = Request)
- when (Code =:= 200) orelse (Code =:= 206) ->
+ when ?IS_STREAMED(Code) ->
?hcrt("start stream - self:once", [{code, Code}]),
Msg = httpc_response:stream_start(Headers, Request, self()),
httpc_response:send(Request#request.from, Msg),
{ok, Request};
start_stream({_Version, Code, _ReasonPhrase}, _Headers,
#request{stream = Filename} = Request)
- when ((Code =:= 200) orelse (Code =:= 206)) andalso is_list(Filename) ->
+ when ?IS_STREAMED(Code) andalso is_list(Filename) ->
?hcrt("start stream", [{code, Code}, {filename, Filename}]),
case file:open(Filename, [write, raw, append, delayed_write]) of
{ok, Fd} ->
@@ -1712,13 +1720,15 @@ end_stream(SL, R) ->
next_body_chunk(#state{request = #request{stream = {self, once}},
once = once,
- session = Session} = State) ->
+ session = Session} = State,
+ Code) when ?IS_STREAMED(Code) ->
activate_once(Session),
State#state{once = inactive};
next_body_chunk(#state{request = #request{stream = {self, once}},
- once = inactive} = State) ->
+ once = inactive} = State,
+ Code) when ?IS_STREAMED(Code) ->
State; %% Wait for user to call stream_next
-next_body_chunk(#state{session = Session} = State) ->
+next_body_chunk(#state{session = Session} = State, _) ->
activate_once(Session),
State.
@@ -1817,11 +1827,13 @@ host_header(_, URI) ->
tls_upgrade(#state{status =
{ssl_tunnel,
#request{settings =
- #http_options{ssl = {_, TLSOptions} = SocketType},
- address = Address} = Request},
+ #http_options{ssl = {_, TLSOptions0} = SocketType},
+ address = {Host, _} = Address} = Request},
session = #session{socket = TCPSocket} = Session0,
options = Options} = State) ->
+ TLSOptions = maybe_add_sni(Host, TLSOptions0),
+
case ssl:connect(TCPSocket, TLSOptions) of
{ok, TLSSocket} ->
ClientClose = httpc_request:is_client_closing(Request#request.headers),
@@ -1852,6 +1864,15 @@ tls_upgrade(#state{status =
{stop, normal, State#state{request = Request}}
end.
+maybe_add_sni(Host, Options) ->
+ case http_util:is_hostname(Host) andalso
+ not lists:keymember(server_name_indication, 1, Options) of
+ true ->
+ [{server_name_indication, Host} | Options];
+ false ->
+ Options
+ end.
+
%% ---------------------------------------------------------------------
%% Session wrappers
%% ---------------------------------------------------------------------
diff --git a/lib/inets/src/http_lib/http_chunk.erl b/lib/inets/src/http_lib/http_chunk.erl
index 9476ea9f5f..7325f24809 100644
--- a/lib/inets/src/http_lib/http_chunk.erl
+++ b/lib/inets/src/http_lib/http_chunk.erl
@@ -25,7 +25,7 @@
-include("http_internal.hrl").
%% API
--export([decode/3, encode/1, encode_last/0, handle_headers/2]).
+-export([decode/3, encode/1, encode_last/0, encode_last/1, handle_headers/2]).
%% Callback API - used for example if the chunkedbody is received a
%% little at a time on a socket.
-export([decode_size/1, ignore_extensions/1, decode_data/1, decode_trailer/1]).
@@ -57,7 +57,7 @@
%%-------------------------------------------------------------------------
decode(ChunkedBody, MaxBodySize, MaxHeaderSize) ->
%% Note decode_size will call decode_data.
- decode_size([ChunkedBody, <<>>, [],
+ decode_size([ChunkedBody, <<>>, [], 0,
{MaxBodySize, <<>>, 0, MaxHeaderSize}]).
%%-------------------------------------------------------------------------
@@ -85,6 +85,11 @@ encode(Chunk) when is_list(Chunk)->
encode_last() ->
<<$0, ?CR, ?LF, ?CR, ?LF >>.
+encode_last([]) ->
+ encode_last();
+encode_last(Trailers0) ->
+ Trailers = list_to_binary(encode_trailers(Trailers0)),
+ <<$0, ?CR, ?LF, Trailers/binary>>.
%%-------------------------------------------------------------------------
%% handle_headers(HeaderRecord, ChunkedHeaders) -> NewHeaderRecord
@@ -120,65 +125,80 @@ handle_headers(ResponseHeaderRecord = #http_response_h{}, ChunkedHeaders) ->
%% Functions that may be returned during the decoding process
%% if the input data is incompleate.
-decode_size([Bin, Rest, HexList, Info]) ->
- decode_size(<<Rest/binary, Bin/binary>>, HexList, Info).
+decode_size([Bin, Rest, HexList, AccSize, Info]) ->
+ decode_size(<<Rest/binary, Bin/binary>>, HexList, AccSize, Info).
-ignore_extensions([Bin, Rest, NextFunction]) ->
- ignore_extensions(<<Rest/binary, Bin/binary>>, NextFunction).
+ignore_extensions([Bin, Rest, RemainingSize, TotalMaxHeaderSize, NextFunction]) ->
+ ignore_extensions(<<Rest/binary, Bin/binary>>, RemainingSize, TotalMaxHeaderSize, NextFunction).
decode_data([Bin, ChunkSize, TotalChunk, Info]) ->
decode_data(ChunkSize, <<TotalChunk/binary, Bin/binary>>, Info).
-decode_trailer([Bin, Rest, Header, Headers, MaxHeaderSize, Body,
- BodyLength]) ->
+decode_trailer([Bin, Rest, Header, Headers, Body,
+ BodyLength, RemainingSize, TotalMaxHeaderSize]) ->
decode_trailer(<<Rest/binary, Bin/binary>>,
- Header, Headers, MaxHeaderSize, Body, BodyLength).
+ Header, Headers, Body, BodyLength, RemainingSize, TotalMaxHeaderSize).
%%%========================================================================
%%% Internal functions
%%%========================================================================
-decode_size(<<>>, HexList, Info) ->
- {?MODULE, decode_size, [<<>>, HexList, Info]};
-decode_size(Data = <<?CR, ?LF, ChunkRest/binary>>, HexList,
+decode_size(_, _, AccHeaderSize, {_,_,_, MaxHeaderSize}) when
+ AccHeaderSize > MaxHeaderSize ->
+ throw({error, {header_too_long, {max, MaxHeaderSize}}});
+
+decode_size(<<>>, HexList, AccHeaderSize, Info) ->
+ {?MODULE, decode_size, [<<>>, HexList, AccHeaderSize, Info]};
+decode_size(Data = <<?CR, ?LF, ChunkRest/binary>>, HexList, AccHeaderSize,
{MaxBodySize, Body,
AccLength,
MaxHeaderSize}) ->
- ChunkSize = http_util:hexlist_to_integer(lists:reverse(HexList)),
- case ChunkSize of
+ try http_util:hexlist_to_integer(lists:reverse(string:strip(HexList, left))) of
0 -> % Last chunk, there was no data
- ignore_extensions(Data, {?MODULE, decode_trailer,
- [<<>>, [],[], MaxHeaderSize,
- Body,
- integer_to_list(AccLength)]});
- _ ->
+ ignore_extensions(Data, remaing_size(MaxHeaderSize, AccHeaderSize), MaxHeaderSize,
+ {?MODULE, decode_trailer,
+ [<<>>, [],[],
+ Body,
+ integer_to_list(AccLength)]});
+ ChunkSize ->
%% Note decode_data may call decode_size again if there
%% is more than one chunk, hence here is where the last parameter
%% to this function comes in.
decode_data(ChunkSize, ChunkRest, {MaxBodySize, Body,
- ChunkSize + AccLength ,
+ ChunkSize + AccLength,
MaxHeaderSize})
+ catch
+ _:_ ->
+ throw({error, {chunk_size, lists:reverse(HexList)}})
end;
-decode_size(<<";", Rest/binary>>, HexList, Info) ->
+decode_size(<<";", Rest/binary>>, HexList, AccHeaderSize, {_,_,_, MaxHeaderSize} = Info) ->
%% Note ignore_extensions will call decode_size/1 again when
%% it ignored all extensions.
- ignore_extensions(Rest, {?MODULE, decode_size, [<<>>, HexList, Info]});
-decode_size(<<?CR>> = Data, HexList, Info) ->
- {?MODULE, decode_size, [Data, HexList, Info]};
-decode_size(<<Octet, Rest/binary>>, HexList, Info) ->
- decode_size(Rest, [Octet | HexList], Info).
+ ignore_extensions(Rest, remaing_size(MaxHeaderSize, AccHeaderSize), MaxHeaderSize,
+ {?MODULE, decode_size, [<<>>, HexList, AccHeaderSize, Info]});
+decode_size(<<?CR>> = Data, HexList, AccHeaderSize, Info) ->
+ {?MODULE, decode_size, [Data, HexList, AccHeaderSize, Info]};
+decode_size(<<Octet, Rest/binary>>, HexList, AccHeaderSize, Info) ->
+ decode_size(Rest, [Octet | HexList], AccHeaderSize + 1, Info).
%% "All applications MUST ignore chunk-extension extensions they
%% do not understand.", see RFC 2616 Section 3.6.1 We don't
%% understand any extension...
-ignore_extensions(<<>>, NextFunction) ->
- {?MODULE, ignore_extensions, [<<>>, NextFunction]};
-ignore_extensions(Data = <<?CR, ?LF, _ChunkRest/binary>>,
+ignore_extensions(_, 0, TotalMaxHeaderSize, _) ->
+ throw({error, {header_too_long, {max, TotalMaxHeaderSize}}});
+ignore_extensions(<<>>, RemainingSize, TotalMaxHeaderSize, NextFunction) ->
+ {?MODULE, ignore_extensions, [<<>>, RemainingSize, TotalMaxHeaderSize, NextFunction]};
+ignore_extensions(Data = <<?CR, ?LF, _ChunkRest/binary>>, RemainingSize, TotalMaxHeaderSize,
{Module, Function, Args}) ->
- Module:Function([Data | Args]);
-ignore_extensions(<<?CR>> = Data, NextFunction) ->
- {?MODULE, ignore_extensions, [Data, NextFunction]};
-ignore_extensions(<<_Octet, Rest/binary>>, NextFunction) ->
- ignore_extensions(Rest, NextFunction).
+ case Function of
+ decode_trailer ->
+ Module:Function([Data | Args ++ [RemainingSize, TotalMaxHeaderSize]]);
+ _ ->
+ Module:Function([Data | Args])
+ end;
+ignore_extensions(<<?CR>> = Data, RemainingSize, TotalMaxHeaderSize, NextFunction) ->
+ {?MODULE, ignore_extensions, [Data, RemainingSize, TotalMaxHeaderSize, NextFunction]};
+ignore_extensions(<<_Octet, Rest/binary>>, RemainingSize, TotalMaxHeaderSize, NextFunction) ->
+ ignore_extensions(Rest, remaing_size(RemainingSize, 1), TotalMaxHeaderSize, NextFunction).
decode_data(ChunkSize, TotalChunk,
Info = {MaxBodySize, BodySoFar, AccLength, MaxHeaderSize})
@@ -190,83 +210,89 @@ decode_data(ChunkSize, TotalChunk,
%% once it ignored all extensions.
{?MODULE, ignore_extensions,
[<<>>,
- {?MODULE, decode_trailer, [<<>>, [],[], MaxHeaderSize,
+ {?MODULE, decode_trailer, [<<>>, [],[],
<<BodySoFar/binary, Data/binary>>,
integer_to_list(AccLength)]}]};
<<Data:ChunkSize/binary, ?CR, ?LF, "0", ";", Rest/binary>> ->
%% Note ignore_extensions will call decode_trailer/1
%% once it ignored all extensions.
- ignore_extensions(Rest, {?MODULE, decode_trailer,
- [<<>>, [],[], MaxHeaderSize,
+ ignore_extensions(Rest, MaxHeaderSize, MaxHeaderSize,
+ {?MODULE, decode_trailer,
+ [<<>>, [],[],
<<BodySoFar/binary, Data/binary>>,
integer_to_list(AccLength)]});
<<Data:ChunkSize/binary, ?CR, ?LF, "0", ?CR, ?LF>> ->
- {?MODULE, decode_trailer, [<<?CR, ?LF>>, [],[], MaxHeaderSize,
+ {?MODULE, decode_trailer, [<<?CR, ?LF>>, [],[],
<<BodySoFar/binary, Data/binary>>,
- integer_to_list(AccLength)]};
+ integer_to_list(AccLength), MaxHeaderSize, MaxHeaderSize]};
<<Data:ChunkSize/binary, ?CR, ?LF, "0", ?CR, ?LF, Rest/binary>> ->
- decode_trailer(<<?CR, ?LF, Rest/binary>>, [],[], MaxHeaderSize,
+ decode_trailer(<<?CR, ?LF, Rest/binary>>, [],[],
<<BodySoFar/binary, Data/binary>>,
- integer_to_list(AccLength));
- %% There are more chunks, so here we go agin...
+ integer_to_list(AccLength), MaxHeaderSize, MaxHeaderSize);
+ %% There are more chunks, so here we go again...
<<Data:ChunkSize/binary, ?CR, ?LF>> ->
NewBody = <<BodySoFar/binary, Data/binary>>,
- {?MODULE, decode_size, [<<>>, [], {MaxBodySize, NewBody, AccLength, MaxHeaderSize}]};
+ {?MODULE, decode_size, [<<>>, [], 0, {MaxBodySize, NewBody, AccLength, MaxHeaderSize}]};
<<Data:ChunkSize/binary, ?CR, ?LF, Rest/binary>>
when (AccLength < MaxBodySize) or (MaxBodySize == nolimit) ->
- decode_size(Rest, [],
+ decode_size(Rest, [], 0,
{MaxBodySize, <<BodySoFar/binary, Data/binary>>,
AccLength, MaxHeaderSize});
<<_:ChunkSize/binary, ?CR, ?LF, _/binary>> ->
- throw({error, body_too_big});
+ throw({error, {body_too_big, {max, MaxBodySize}}});
_ ->
{?MODULE, decode_data, [ChunkSize, TotalChunk, Info]}
end;
decode_data(ChunkSize, TotalChunk, Info) ->
{?MODULE, decode_data, [ChunkSize, TotalChunk, Info]}.
-decode_trailer(<<>>, Header, Headers, MaxHeaderSize, Body, BodyLength) ->
- {?MODULE, decode_trailer, [<<>>, Header, Headers, MaxHeaderSize, Body,
- BodyLength]};
-
+decode_trailer(_,_,_,_,_, 0, TotalMaxHeaderSize) ->
+ throw({error, {header_too_long, {max, TotalMaxHeaderSize}}});
+decode_trailer(<<>>, Header, Headers, Body, BodyLength, RemainingSize, TotalMaxHeaderSize) ->
+ {?MODULE, decode_trailer, [<<>>, Header, Headers, Body,
+ BodyLength, RemainingSize, TotalMaxHeaderSize]};
%% Note: If Bin is not empty it is part of a pipelined request/response.
-decode_trailer(<<?CR,?LF,?CR,?LF, Bin/binary>>, [], [], _, Body, BodyLength) ->
+decode_trailer(<<?CR,?LF,?CR,?LF, Bin/binary>>, [], [], Body, BodyLength, _, _) ->
{ok, {["content-length:" ++ BodyLength], <<Body/binary, Bin/binary>>}};
decode_trailer(<<?CR,?LF,?CR,?LF, Bin/binary>>,
- Header, Headers, MaxHeaderSize, Body, BodyLength) ->
+ Header, Headers, Body, BodyLength, _, _) ->
NewHeaders = case Header of
[] ->
Headers;
_ ->
[lists:reverse(Header) | Headers]
end,
- Length = length(NewHeaders),
- case Length > MaxHeaderSize of
- true ->
- throw({error, {header_too_long, MaxHeaderSize,
- MaxHeaderSize-Length}});
- false ->
- {ok, {["content-length:" ++ BodyLength | NewHeaders],
- <<Body/binary, Bin/binary>>}}
- end;
-decode_trailer(<<?CR,?LF,?CR>> = Data, Header, Headers, MaxHeaderSize,
- Body, BodyLength) ->
- {?MODULE, decode_trailer, [Data, Header, Headers, MaxHeaderSize, Body,
- BodyLength]};
-decode_trailer(<<?CR,?LF>> = Data, Header, Headers, MaxHeaderSize,
- Body, BodyLength) ->
- {?MODULE, decode_trailer, [Data, Header, Headers, MaxHeaderSize, Body,
- BodyLength]};
-decode_trailer(<<?CR>> = Data, Header, Headers, MaxHeaderSize,
- Body, BodyLength) ->
- {?MODULE, decode_trailer, [Data, Header, Headers, MaxHeaderSize, Body,
- BodyLength]};
-decode_trailer(<<?CR, ?LF, Rest/binary>>, Header, Headers,
- MaxHeaderSize, Body, BodyLength) ->
+ {ok, {["content-length:" ++ BodyLength | NewHeaders],
+ <<Body/binary, Bin/binary>>}};
+decode_trailer(<<?CR,?LF,?CR>> = Data, Header, Headers,
+ Body, BodyLength, RemainingSize, TotalMaxHeaderSize) ->
+ {?MODULE, decode_trailer, [Data, Header, Headers, Body,
+ BodyLength, RemainingSize, TotalMaxHeaderSize]};
+decode_trailer(<<?CR,?LF>> = Data, Header, Headers,
+ Body, BodyLength, RemainingSize, TotalMaxHeaderSize) ->
+ {?MODULE, decode_trailer, [Data, Header, Headers, Body,
+ BodyLength, RemainingSize, TotalMaxHeaderSize]};
+decode_trailer(<<?CR>> = Data, Header, Headers,
+ Body, BodyLength, RemainingSize, TotalMaxHeaderSize) ->
+ {?MODULE, decode_trailer, [Data, Header, Headers, Body,
+ BodyLength, RemainingSize, TotalMaxHeaderSize]};
+decode_trailer(<<?CR, ?LF, Rest/binary>>, Header, Headers, Body, BodyLength, RemainingSize, TotalMaxHeaderSize) ->
decode_trailer(Rest, [], [lists:reverse(Header) | Headers],
- MaxHeaderSize, Body, BodyLength);
+ Body, BodyLength, RemainingSize, TotalMaxHeaderSize);
+decode_trailer(<<Octet, Rest/binary>>, Header, Headers, Body,
+ BodyLength, RemainingSize, TotalMaxHeaderSize) ->
+ decode_trailer(Rest, [Octet | Header], Headers,
+ Body, BodyLength, remaing_size(RemainingSize, 1), TotalMaxHeaderSize).
+
+remaing_size(nolimit, _) ->
+ nolimit;
+remaing_size(Total, Consumed) ->
+ Total - Consumed.
-decode_trailer(<<Octet, Rest/binary>>, Header, Headers, MaxHeaderSize, Body,
- BodyLength) ->
- decode_trailer(Rest, [Octet | Header], Headers, MaxHeaderSize,
- Body, BodyLength).
+encode_trailers(Trailers) ->
+ encode_trailers(Trailers, "").
+
+encode_trailers([], Acc) ->
+ Acc ++ ?CRLF ++ ?CRLF;
+encode_trailers([{Header, Value} | Rest], Acc) ->
+ encode_trailers(Rest, Header ++ ":" ++ Value ++ ?CRLF ++ Acc).
diff --git a/lib/inets/src/http_lib/http_response.erl b/lib/inets/src/http_lib/http_response.erl
index d13670700c..42e5dd263d 100644
--- a/lib/inets/src/http_lib/http_response.erl
+++ b/lib/inets/src/http_lib/http_response.erl
@@ -65,6 +65,8 @@ header_list(Headers) ->
%%%========================================================================
fill_headers([], _, Headers) ->
Headers;
+fill_headers([[]], _, Headers) ->
+ Headers;
fill_headers([[Ch|HeaderFold]|Tail], Folded, Headers)
when Ch == $\t; Ch == $\s ->
fill_headers(Tail, [HeaderFold|Folded], Headers);
diff --git a/lib/inets/src/http_lib/http_transport.erl b/lib/inets/src/http_lib/http_transport.erl
index 719dc4c425..ab6afe9c6c 100644
--- a/lib/inets/src/http_lib/http_transport.erl
+++ b/lib/inets/src/http_lib/http_transport.erl
@@ -40,12 +40,6 @@
-include_lib("inets/src/inets_app/inets_internal.hrl").
-include("http_internal.hrl").
--define(SERVICE, httpl).
--define(hlri(Label, Content), ?report_important(Label, ?SERVICE, Content)).
--define(hlrv(Label, Content), ?report_verbose(Label, ?SERVICE, Content)).
--define(hlrd(Label, Content), ?report_debug(Label, ?SERVICE, Content)).
--define(hlrt(Label, Content), ?report_trace(Label, ?SERVICE, Content)).
-
%%%=========================================================================
%%% Internal application API
@@ -55,38 +49,27 @@
%% start(SocketType) -> ok | {error, Reason}
%% SocketType = ip_comm | {ssl, _}
%%
-%% Description: Makes sure inet_db or ssl is started.
+%% Description: Makes sure ssl is started.
%%-------------------------------------------------------------------------
start(ip_comm) ->
- do_start_ip_comm();
-
-%% This is just for backward compatibillity
+ ok;
+start({ip_comm, _}) ->
+ ok;
start({ssl, _}) ->
do_start_ssl();
start({essl, _}) ->
do_start_ssl().
-
-do_start_ip_comm() ->
- case inet_db:start() of
- {ok, _} ->
- ok;
- {error, {already_started, _}} ->
- ok;
- Error ->
- Error
- end.
-
do_start_ssl() ->
- case ssl:start() of
- ok ->
- ok;
- {error, {already_started,_}} ->
- ok;
- Error ->
- Error
+ try lists:foreach(fun(App) ->
+ ok = application:ensure_started(App)
+ end,
+ [crypto, asn1, public_key, ssl])
+ catch
+ _:Reason ->
+ {error, Reason}
end.
-
+
%%-------------------------------------------------------------------------
%% connect(SocketType, Address, Options, Timeout) ->
@@ -103,12 +86,8 @@ do_start_ssl() ->
connect(SocketType, Address, Opts) ->
connect(SocketType, Address, Opts, infinity).
-
-connect(ip_comm = _SocketType, {Host, Port}, Opts0, Timeout)
- when is_list(Opts0) ->
- Opts = [binary, {packet, 0}, {active, false}, {reuseaddr, true} | Opts0],
- ?hlrt("connect using gen_tcp",
- [{host, Host}, {port, Port}, {opts, Opts}, {timeout, Timeout}]),
+connect(ip_comm, {Host, Port}, Opts0, Timeout) ->
+ Opts = [binary, {packet, 0}, {active, false}, {reuseaddr, true} | Opts0 ],
try gen_tcp:connect(Host, Port, Opts, Timeout) of
{ok, _} = OK ->
OK;
@@ -127,11 +106,6 @@ connect({ssl, SslConfig}, Address, Opts, Timeout) ->
connect({essl, SslConfig}, {Host, Port}, Opts0, Timeout) ->
Opts = [binary, {active, false}, {ssl_imp, new} | Opts0] ++ SslConfig,
- ?hlrt("connect using essl",
- [{host, Host},
- {port, Port},
- {ssl_config, SslConfig},
- {timeout, Timeout}]),
case (catch ssl:connect(Host, Port, Opts, Timeout)) of
{'EXIT', Reason} ->
{error, {eoptions, Reason}};
@@ -156,29 +130,23 @@ connect({essl, SslConfig}, {Host, Port}, Opts0, Timeout) ->
%% reason for this to enable a HTTP-server not running as root to use
%% port 80.
%%-------------------------------------------------------------------------
-listen(ip_comm = _SocketType, Addr, Port, Fd, IpFamily) ->
- listen_ip_comm(Addr, Port, Fd, IpFamily);
-
+listen(ip_comm, Addr, Port, Fd, IpFamily) ->
+ listen_ip_comm(Addr, Port, [], Fd, IpFamily);
+
+listen({ip_comm, SockOpts}, Addr, Port, Fd, IpFamily) ->
+ listen_ip_comm(Addr, Port, SockOpts, Fd, IpFamily);
+
listen({essl, SSLConfig}, Addr, Port, Fd, IpFamily) ->
listen_ssl(Addr, Port, Fd, SSLConfig, IpFamily, []).
-listen(ip_comm = _SocketType, Addr, Port, IpFamily) ->
- listen_ip_comm(Addr, Port, undefined, IpFamily);
+listen(ip_comm, Addr, Port, IpFamily) ->
+ listen_ip_comm(Addr, Port, [], undefined, IpFamily);
%% Wrapper for backaward compatibillity
listen({ssl, SSLConfig}, Addr, Port, IpFamily) ->
- ?hlrt("listen (wrapper)",
- [{addr, Addr},
- {port, Port},
- {ssl_config, SSLConfig}]),
listen({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, Addr, Port, IpFamily);
-
listen({essl, SSLConfig}, Addr, Port, IpFamily) ->
- ?hlrt("listen (essl)",
- [{addr, Addr},
- {port, Port},
- {ssl_config, SSLConfig}]),
{SSLConfig2, ExtraOpts} = case proplists:get_value(log_alert, SSLConfig, undefined) of
undefined ->
{SSLConfig, []};
@@ -187,83 +155,30 @@ listen({essl, SSLConfig}, Addr, Port, IpFamily) ->
end,
listen_ssl(Addr, Port, undefined, SSLConfig2, IpFamily, ExtraOpts).
-listen_ip_comm(Addr, Port, Fd, IpFamily) ->
- case (catch do_listen_ip_comm(Addr, Port, Fd, IpFamily)) of
+listen_ip_comm(Addr, Port, SockOpts, Fd, IpFamily) ->
+ case (catch do_listen_ip_comm(Addr, Port, SockOpts, Fd, IpFamily)) of
{'EXIT', Reason} ->
{error, {exit, Reason}};
Else ->
Else
end.
-do_listen_ip_comm(Addr, Port, Fd, IpFamily) ->
- {NewPort, Opts} = get_socket_info(Addr, Port, Fd),
- case IpFamily of
- inet6fb4 ->
- Opts2 = [inet6 | Opts],
- ?hlrt("try ipv6 listen", [{port, NewPort}, {opts, Opts2}]),
- case (catch gen_tcp:listen(NewPort, Opts2)) of
- {error, Reason} when ((Reason =:= nxdomain) orelse
- (Reason =:= eafnosupport)) ->
- Opts3 = [inet | Opts],
- ?hlrt("ipv6 listen failed - try ipv4 instead",
- [{reason, Reason}, {port, NewPort}, {opts, Opts3}]),
- gen_tcp:listen(NewPort, Opts3);
-
- %% This is when a given hostname has resolved to a
- %% IPv4-address. The inet6-option together with a
- %% {ip, IPv4} option results in badarg
- {'EXIT', Reason} ->
- Opts3 = [inet | Opts],
- ?hlrt("ipv6 listen exit - try ipv4 instead",
- [{reason, Reason}, {port, NewPort}, {opts, Opts3}]),
- gen_tcp:listen(NewPort, Opts3);
-
- Other ->
- ?hlrt("ipv6 listen done", [{other, Other}]),
- Other
- end;
- _ ->
- Opts2 = [IpFamily | Opts],
- ?hlrt("listen", [{port, NewPort}, {opts, Opts2}]),
- gen_tcp:listen(NewPort, Opts2)
- end.
+do_listen_ip_comm(Addr, Port, SockOpts, Fd, IpFamily) ->
+ Backlog = proplists:get_value(backlog, SockOpts, 128),
+ {NewPort, Opts} = get_socket_info(Addr, Port, Fd,
+ [{backlog, Backlog}, {reuseaddr, true} | SockOpts]),
+ Opts2 = [IpFamily | Opts],
+ gen_tcp:listen(NewPort, Opts2).
listen_ssl(Addr, Port, Fd, Opts0, IpFamily, ExtraOpts) ->
- {NewPort, SockOpt} = get_socket_info(Addr, Port, Fd),
+ Backlog = proplists:get_value(backlog, Opts0, 128),
+ {NewPort, SockOpt} = get_socket_info(Addr, Port, Fd,
+ [{backlog, Backlog}, {reuseaddr, true}]),
Opts = SockOpt ++ Opts0,
- case IpFamily of
- inet6fb4 ->
- Opts2 = [inet6 | Opts] ++ ExtraOpts,
- ?hlrt("try ipv6 listen", [{opts, Opts2}]),
- case (catch ssl:listen(Port, Opts2)) of
- {error, Reason} when ((Reason =:= nxdomain) orelse
- (Reason =:= eafnosupport)) ->
- Opts3 = [inet | Opts] ++ ExtraOpts,
- ?hlrt("ipv6 listen failed - try ipv4 instead",
- [{reason, Reason}, {opts, Opts3}]),
- ssl:listen(NewPort, Opts3);
-
- {'EXIT', Reason} ->
- Opts3 = [inet | Opts] ++ ExtraOpts,
- ?hlrt("ipv6 listen exit - try ipv4 instead",
- [{reason, Reason}, {opts, Opts3}]),
- ssl:listen(NewPort, Opts3);
-
- Other ->
- ?hlrt("ipv6 listen done", [{other, Other}]),
- Other
- end;
-
- _ ->
- Opts2 = [IpFamily | Opts],
- ?hlrt("listen", [{opts, Opts2}]),
- ssl:listen(NewPort, Opts2 ++ ExtraOpts)
- end.
+ Opts2 = [IpFamily | Opts],
+ ssl:listen(NewPort, Opts2 ++ ExtraOpts).
-
-
-get_socket_info(Addr, Port, Fd) ->
- BaseOpts = [{backlog, 128}, {reuseaddr, true}],
+get_socket_info(Addr, Port, Fd, BaseOpts) ->
%% The presence of a file descriptor takes precedence
case Fd of
undefined ->
@@ -288,6 +203,8 @@ accept(SocketType, ListenSocket) ->
accept(ip_comm, ListenSocket, Timeout) ->
gen_tcp:accept(ListenSocket, Timeout);
+accept({ip_comm, _}, ListenSocket, Timeout) ->
+ gen_tcp:accept(ListenSocket, Timeout);
%% Wrapper for backaward compatibillity
accept({ssl, SSLConfig}, ListenSocket, Timeout) ->
@@ -307,6 +224,8 @@ accept({essl, _SSLConfig}, ListenSocket, Timeout) ->
%%-------------------------------------------------------------------------
controlling_process(ip_comm, Socket, NewOwner) ->
gen_tcp:controlling_process(Socket, NewOwner);
+controlling_process({ip_comm, _}, Socket, NewOwner) ->
+ gen_tcp:controlling_process(Socket, NewOwner);
%% Wrapper for backaward compatibillity
controlling_process({ssl, SSLConfig}, Socket, NewOwner) ->
@@ -325,7 +244,8 @@ controlling_process({essl, _}, Socket, NewOwner) ->
%% gen_tcp or ssl.
%%-------------------------------------------------------------------------
setopts(ip_comm, Socket, Options) ->
- ?hlrt("ip_comm setopts", [{socket, Socket}, {options, Options}]),
+ inet:setopts(Socket, Options);
+setopts({ip_comm, _}, Socket, Options) ->
inet:setopts(Socket, Options);
%% Wrapper for backaward compatibillity
@@ -333,10 +253,7 @@ setopts({ssl, SSLConfig}, Socket, Options) ->
setopts({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, Socket, Options);
setopts({essl, _}, Socket, Options) ->
- ?hlrt("[e]ssl setopts", [{socket, Socket}, {options, Options}]),
- Reason = (catch ssl:setopts(Socket, Options)),
- ?hlrt("[e]ssl setopts result", [{reason, Reason}]),
- Reason.
+ (catch ssl:setopts(Socket, Options)).
%%-------------------------------------------------------------------------
@@ -350,8 +267,10 @@ getopts(SocketType, Socket) ->
Opts = [packet, packet_size, recbuf, sndbuf, priority, tos, send_timeout],
getopts(SocketType, Socket, Opts).
+getopts({ip_comm, _}, Socket, Options) ->
+ getopts(ip_comm, Socket, Options);
+
getopts(ip_comm, Socket, Options) ->
- ?hlrt("ip_comm getopts", [{socket, Socket}, {options, Options}]),
case inet:getopts(Socket, Options) of
{ok, SocketOpts} ->
SocketOpts;
@@ -364,7 +283,6 @@ getopts({ssl, SSLConfig}, Socket, Options) ->
getopts({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, Socket, Options);
getopts({essl, _}, Socket, Options) ->
- ?hlrt("essl getopts", [{socket, Socket}, {options, Options}]),
getopts_ssl(Socket, Options).
getopts_ssl(Socket, Options) ->
@@ -384,7 +302,6 @@ getopts_ssl(Socket, Options) ->
%% Description: Gets the socket stats values for the socket
%%-------------------------------------------------------------------------
getstat(ip_comm = _SocketType, Socket) ->
- ?hlrt("ip_comm getstat", [{socket, Socket}]),
case inet:getstat(Socket) of
{ok, Stats} ->
Stats;
@@ -409,6 +326,8 @@ getstat({essl, _} = _SocketType, _Socket) ->
%%-------------------------------------------------------------------------
send(ip_comm, Socket, Message) ->
gen_tcp:send(Socket, Message);
+send({ip_comm, _}, Socket, Message) ->
+ gen_tcp:send(Socket, Message);
%% Wrapper for backaward compatibillity
send({ssl, SSLConfig}, Socket, Message) ->
@@ -417,7 +336,6 @@ send({ssl, SSLConfig}, Socket, Message) ->
send({essl, _}, Socket, Message) ->
ssl:send(Socket, Message).
-
%%-------------------------------------------------------------------------
%% close(SocketType, Socket) -> ok | {error, Reason}
%% SocketType = ip_comm | {ssl, _}
@@ -427,6 +345,8 @@ send({essl, _}, Socket, Message) ->
%%-------------------------------------------------------------------------
close(ip_comm, Socket) ->
gen_tcp:close(Socket);
+close({ip_comm, []}, Socket) ->
+ gen_tcp:close(Socket);
%% Wrapper for backaward compatibillity
close({ssl, SSLConfig}, Socket) ->
@@ -448,6 +368,8 @@ close({essl, _}, Socket) ->
%%-------------------------------------------------------------------------
peername(ip_comm, Socket) ->
do_peername(inet:peername(Socket));
+peername({ip_comm, _}, Socket) ->
+ do_peername(inet:peername(Socket));
%% Wrapper for backaward compatibillity
peername({ssl, SSLConfig}, Socket) ->
@@ -480,7 +402,8 @@ do_peername({error, _}) ->
%%-------------------------------------------------------------------------
sockname(ip_comm, Socket) ->
do_sockname(inet:sockname(Socket));
-
+sockname({ip_comm, _}, Socket) ->
+ do_sockname(inet:sockname(Socket));
%% Wrapper for backaward compatibillity
sockname({ssl, SSLConfig}, Socket) ->
sockname({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, Socket);
@@ -555,28 +478,13 @@ sock_opts(Opts) ->
%% -- negotiate --
negotiate(ip_comm,_,_) ->
- ?hlrt("negotiate(ip_comm)", []),
+ ok;
+negotiate({ip_comm, _},_,_) ->
ok;
negotiate({ssl, SSLConfig}, Socket, Timeout) ->
- ?hlrt("negotiate(ssl)", []),
negotiate({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, Socket, Timeout);
negotiate({essl, _}, Socket, Timeout) ->
- ?hlrt("negotiate(essl)", []),
negotiate_ssl(Socket, Timeout).
negotiate_ssl(Socket, Timeout) ->
- ?hlrt("negotiate_ssl", [{socket, Socket}, {timeout, Timeout}]),
- case ssl:ssl_accept(Socket, Timeout) of
- ok ->
- ok;
- {error, Reason} ->
- ?hlrd("negotiate_ssl - accept failed", [{reason, Reason}]),
- %% Look for "valid" error reasons
- ValidReasons = [timeout, econnreset, esslaccept, esslerrssl],
- case lists:member(Reason, ValidReasons) of
- true ->
- {error, normal};
- false ->
- {error, Reason}
- end
- end.
+ ssl:ssl_accept(Socket, Timeout).
diff --git a/lib/inets/src/http_lib/http_util.erl b/lib/inets/src/http_lib/http_util.erl
index 0d07231302..aafa97afee 100644
--- a/lib/inets/src/http_lib/http_util.erl
+++ b/lib/inets/src/http_lib/http_util.erl
@@ -152,27 +152,11 @@ convert_netscapecookie_date([_D,_A,_Y, _SP,
Sec=list_to_integer([S1,S2]),
{{Year,Month,Day},{Hour,Min,Sec}}.
-hexlist_to_integer([]) ->
- empty;
-%%When the string only contains one value its eaasy done.
-%% 0-9
-hexlist_to_integer([Size]) when (Size >= 48) andalso (Size =< 57) ->
- Size - 48;
-%% A-F
-hexlist_to_integer([Size]) when (Size >= 65) andalso (Size =< 70) ->
- Size - 55;
-%% a-f
-hexlist_to_integer([Size]) when (Size >= 97) andalso (Size =< 102) ->
- Size - 87;
-hexlist_to_integer([_Size]) ->
- not_a_num;
+hexlist_to_integer(List) ->
+ list_to_integer(List, 16).
-hexlist_to_integer(Size) ->
- Len = string:span(Size, "1234567890abcdefABCDEF"),
- hexlist_to_integer2(Size, 16 bsl (4 *(Len-2)),0).
-
-integer_to_hexlist(Num)->
- integer_to_hexlist(Num, get_size(Num), []).
+integer_to_hexlist(Int) ->
+ integer_to_list(Int, 16).
convert_month("Jan") -> 1;
convert_month("Feb") -> 2;
@@ -213,51 +197,6 @@ html_encode(Chars) ->
%%%========================================================================
%%% Internal functions
%%%========================================================================
-hexlist_to_integer2([],_Pos,Sum)->
- Sum;
-hexlist_to_integer2([HexVal | HexString], Pos, Sum)
- when HexVal >= 48, HexVal =< 57 ->
- hexlist_to_integer2(HexString, Pos bsr 4, Sum + ((HexVal-48) * Pos));
-
-hexlist_to_integer2([HexVal | HexString], Pos, Sum)
- when HexVal >= 65, HexVal =<70 ->
- hexlist_to_integer2(HexString, Pos bsr 4, Sum + ((HexVal-55) * Pos));
-
-hexlist_to_integer2([HexVal | HexString], Pos, Sum)
- when HexVal>=97, HexVal=<102 ->
- hexlist_to_integer2(HexString, Pos bsr 4, Sum + ((HexVal-87) * Pos));
-
-hexlist_to_integer2(_AfterHexString, _Pos, Sum)->
- Sum.
-
-integer_to_hexlist(Num, Pot, Res) when Pot < 0 ->
- convert_to_ascii([Num | Res]);
-
-integer_to_hexlist(Num,Pot,Res) ->
- Position = (16 bsl (Pot*4)),
- PosVal = Num div Position,
- integer_to_hexlist(Num - (PosVal*Position), Pot-1, [PosVal | Res]).
-
-get_size(Num)->
- get_size(Num, 0).
-
-get_size(Num, Pot) when Num < (16 bsl(Pot *4)) ->
- Pot-1;
-
-get_size(Num, Pot) ->
- get_size(Num, Pot+1).
-
-convert_to_ascii(RevesedNum) ->
- convert_to_ascii(RevesedNum, []).
-
-convert_to_ascii([], Num)->
- Num;
-convert_to_ascii([Num | Reversed], Number)
- when (Num > -1) andalso (Num < 10) ->
- convert_to_ascii(Reversed, [Num + 48 | Number]);
-convert_to_ascii([Num | Reversed], Number)
- when (Num > 9) andalso (Num < 16) ->
- convert_to_ascii(Reversed, [Num + 55 | Number]).
char_to_html_entity(Char, Reserved) ->
case sets:is_element(Char, Reserved) of
diff --git a/lib/inets/src/http_server/Makefile b/lib/inets/src/http_server/Makefile
index b9f2290289..1c05d454a5 100644
--- a/lib/inets/src/http_server/Makefile
+++ b/lib/inets/src/http_server/Makefile
@@ -137,7 +137,7 @@ release_spec: opt
$(INSTALL_DIR) "$(RELSYSDIR)/src/http_server"
$(INSTALL_DATA) $(HRL_FILES) $(ERL_FILES) "$(RELSYSDIR)/src/http_server"
$(INSTALL_DIR) "$(RELSYSDIR)/ebin"
- $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) $(BEHAVIOUR_TARGET_FILES) "$(RELSYSDIR)/ebin"
release_docs_spec:
diff --git a/lib/inets/src/http_server/httpd_conf.erl b/lib/inets/src/http_server/httpd_conf.erl
index 7d31989244..62e8a95b19 100644
--- a/lib/inets/src/http_server/httpd_conf.erl
+++ b/lib/inets/src/http_server/httpd_conf.erl
@@ -156,7 +156,7 @@ load("BindAddress " ++ Address0, []) ->
case string:tokens(Address0, [$|]) of
[Address1] ->
?hdrv("load BindAddress", [{address1, Address1}]),
- {clean_address(Address1), inet6fb4};
+ {clean_address(Address1), inet};
[Address1, IpFamilyStr] ->
?hdrv("load BindAddress",
[{address1, Address1},
@@ -353,14 +353,21 @@ clean_address(Addr) ->
make_ipfamily(IpFamilyStr) ->
- IpFamily = list_to_atom(IpFamilyStr),
- case lists:member(IpFamily, [inet, inet6, inet6fb4]) of
- true ->
- IpFamily;
- false ->
- throw({error, {bad_ipfamily, IpFamilyStr}})
- end.
-
+ validate_ipfamily(list_to_atom(IpFamilyStr)).
+
+validate_ipfamily(inet) ->
+ inet;
+validate_ipfamily(inet6) ->
+ inet6;
+%% Backwards compatibility wrapper,
+%% fallback to the default, IPV4,
+%% as it will most proably work.
+%% IPv6 standard moved away from
+%% beeing able to fallback to ipv4
+validate_ipfamily(inet6fb4) ->
+ inet;
+validate_ipfamily(IpFamilyStr) ->
+ throw({error, {bad_ipfamily, IpFamilyStr}}).
%%
%% load_mime_types/1 -> {ok, MimeTypes} | {error, Reason}
@@ -393,20 +400,16 @@ validate_properties2(Properties) ->
undefined ->
case proplists:get_value(sock_type, Properties, ip_comm) of
ip_comm ->
- case proplists:get_value(ipfamily, Properties) of
- undefined ->
- [{bind_address, any},
- {ipfamily, inet6fb4} | Properties];
- _ ->
- [{bind_address, any} | Properties]
- end;
+ add_inet_defaults(Properties);
+ {ip_comm, _} ->
+ add_inet_defaults(Properties);
_ ->
[{bind_address, any} | Properties]
end;
any ->
Properties;
Address0 ->
- IpFamily = proplists:get_value(ipfamily, Properties, inet6fb4),
+ IpFamily = proplists:get_value(ipfamily, Properties, inet),
case httpd_util:ip_address(Address0, IpFamily) of
{ok, Address} ->
Properties1 = proplists:delete(bind_address, Properties),
@@ -418,6 +421,16 @@ validate_properties2(Properties) ->
throw(Error)
end
end.
+
+add_inet_defaults(Properties) ->
+ case proplists:get_value(ipfamily, Properties) of
+ undefined ->
+ [{bind_address, any},
+ {ipfamily, inet} | Properties];
+ _ ->
+ [{bind_address, any} | Properties]
+ end.
+
check_minimum_bytes_per_second(Properties) ->
case proplists:get_value(minimum_bytes_per_second, Properties, false) of
false ->
@@ -487,12 +500,11 @@ validate_config_params([{server_tokens, Value} | _]) ->
validate_config_params([{socket_type, ip_comm} | Rest]) ->
validate_config_params(Rest);
-validate_config_params([{socket_type, Value} | Rest])
- when Value == ssl; Value == essl ->
- validate_config_params(Rest);
-
-validate_config_params([{socket_type, {Value, _}} | Rest])
- when Value == essl orelse Value == ssl ->
+validate_config_params([{socket_type, {Value, Opts}} | Rest]) when Value == ip_comm;
+ Value == ssl;
+ Value == essl ->
+ %% Make sure not to set socket values used internaly
+ validate_config_params(Opts),
validate_config_params(Rest);
validate_config_params([{socket_type, Value} | _]) ->
@@ -622,21 +634,32 @@ validate_config_params([{disable_chunked_transfer_encoding_send, Value} |
validate_config_params([{disable_chunked_transfer_encoding_send, Value} |
_ ]) ->
throw({disable_chunked_transfer_encoding_send, Value});
+validate_config_params([{Name, _} = Opt | _]) when Name == packet;
+ Name == mode;
+ Name == active;
+ Name == reuseaddr ->
+ throw({internaly_handled_opt_can_not_be_set, Opt});
validate_config_params([_| Rest]) ->
validate_config_params(Rest).
-%% It is actually pointless to check bind_address in this way since
-%% we need ipfamily to do it properly...
is_bind_address(any) ->
true;
is_bind_address(Value) ->
- case httpd_util:ip_address(Value, inet6fb4) of
+ case is_bind_address(Value, inet) of
+ false ->
+ is_bind_address(Value, inet6);
+ True ->
+ True
+ end.
+
+is_bind_address(Value, IpFamily) ->
+ case httpd_util:ip_address(Value, IpFamily) of
{ok, _} ->
true;
_ ->
false
end.
-
+
store(ConfigList0) ->
?hdrd("store", []),
try validate_config_params(ConfigList0) of
@@ -776,28 +799,6 @@ remove(ConfigDB) ->
ets:delete(ConfigDB),
ok.
-%% config(ConfigDB) ->
-%% case httpd_util:lookup(ConfigDB, socket_type, ip_comm) of
-%% ssl ->
-%% case ssl_certificate_file(ConfigDB) of
-%% undefined ->
-%% {error,
-%% "Directive SSLCertificateFile "
-%% "not found in the config file"};
-%% SSLCertificateFile ->
-%% {ssl,
-%% SSLCertificateFile++
-%% ssl_certificate_key_file(ConfigDB)++
-%% ssl_verify_client(ConfigDB)++
-%% ssl_ciphers(ConfigDB)++
-%% ssl_password(ConfigDB)++
-%% ssl_verify_depth(ConfigDB)++
-%% ssl_ca_certificate_file(ConfigDB)}
-%% end;
-%% ip_comm ->
-%% ip_comm
-%% end.
-
get_config(Address, Port, Profile) ->
Tab = httpd_util:make_name("httpd_conf", Address, Port, Profile),
@@ -836,6 +837,8 @@ lookup_socket_type(ConfigDB) ->
case httpd_util:lookup(ConfigDB, socket_type, ip_comm) of
ip_comm ->
ip_comm;
+ {ip_comm, _} = Type ->
+ Type;
{Tag, Conf} ->
{Tag, Conf};
SSL when (SSL =:= ssl) orelse (SSL =:= essl) ->
diff --git a/lib/inets/src/http_server/httpd_custom_api.erl b/lib/inets/src/http_server/httpd_custom_api.erl
index 282f3a6ee6..d5a6fa8715 100644
--- a/lib/inets/src/http_server/httpd_custom_api.erl
+++ b/lib/inets/src/http_server/httpd_custom_api.erl
@@ -23,7 +23,8 @@
-callback response_default_headers() ->
[{Key::string(), Value::string()}].
-callback response_header({Key::string(), Value::string()}) ->
- {true, {Key::string(), Value::string()}} | false.
+ {true, {Key::string(), Value::string()}} | false |
+ {true, string()}. %% Used internally to avoid traversing headers twice
-callback request_header({Key::string(), Value::string()}) ->
{true, {Key::string(), Value::string()}} | false.
diff --git a/lib/inets/src/http_server/httpd_example.erl b/lib/inets/src/http_server/httpd_example.erl
index d729affd6d..0222487a4b 100644
--- a/lib/inets/src/http_server/httpd_example.erl
+++ b/lib/inets/src/http_server/httpd_example.erl
@@ -24,7 +24,7 @@
-export([newformat/3]).
%% These are used by the inets test-suite
--export([delay/1]).
+-export([delay/1, chunk_timeout/3]).
print(String) ->
@@ -142,3 +142,11 @@ i(F) -> i(F,[]).
i(F,A) -> io:format(F ++ "~n",A).
sleep(T) -> receive after T -> ok end.
+
+%% ------------------------------------------------------
+
+chunk_timeout(SessionID, _, StrInt) ->
+ mod_esi:deliver(SessionID, "Tranfer-Encoding:chunked/html\r\n\r\n"),
+ mod_esi:deliver(SessionID, top("Test chunk encoding timeout")),
+ timer:sleep(20000),
+ mod_esi:deliver(SessionID, footer()).
diff --git a/lib/inets/src/http_server/httpd_request_handler.erl b/lib/inets/src/http_server/httpd_request_handler.erl
index e5d006c1fd..134576059d 100644
--- a/lib/inets/src/http_server/httpd_request_handler.erl
+++ b/lib/inets/src/http_server/httpd_request_handler.erl
@@ -443,7 +443,7 @@ handle_body(#state{headers = Headers, body = Body, mod = ModData} = State,
MaxHeaderSize, MaxBodySize) ->
case Headers#http_request_h.'transfer-encoding' of
"chunked" ->
- case http_chunk:decode(Body, MaxBodySize, MaxHeaderSize) of
+ try http_chunk:decode(Body, MaxBodySize, MaxHeaderSize) of
{Module, Function, Args} ->
http_transport:setopts(ModData#mod.socket_type,
ModData#mod.socket,
@@ -455,6 +455,14 @@ handle_body(#state{headers = Headers, body = Body, mod = ModData} = State,
http_chunk:handle_headers(Headers, ChunkedHeaders),
handle_response(State#state{headers = NewHeaders,
body = NewBody})
+ catch
+ throw:Error ->
+ httpd_response:send_status(ModData, 400,
+ "Bad input"),
+ Reason = io_lib:format("Chunk decoding failed: ~p~n",
+ [Error]),
+ error_log(Reason, ModData),
+ {stop, normal, State#state{response_sent = true}}
end;
Encoding when is_list(Encoding) ->
httpd_response:send_status(ModData, 501,
@@ -622,21 +630,10 @@ decrease(N) when is_integer(N) ->
decrease(N) ->
N.
-error_log(ReasonString, Info) ->
+error_log(ReasonString, #mod{config_db = ConfigDB}) ->
Error = lists:flatten(
io_lib:format("Error reading request: ~s", [ReasonString])),
- error_log(mod_log, Info, Error),
- error_log(mod_disk_log, Info, Error).
-
-error_log(Mod, #mod{config_db = ConfigDB} = Info, String) ->
- Modules = httpd_util:lookup(ConfigDB, modules,
- [mod_get, mod_head, mod_log]),
- case lists:member(Mod, Modules) of
- true ->
- Mod:error_log(Info, String);
- _ ->
- ok
- end.
+ httpd_util:error_log(ConfigDB, Error).
%%--------------------------------------------------------------------
diff --git a/lib/inets/src/http_server/httpd_response.erl b/lib/inets/src/http_server/httpd_response.erl
index 71243f525a..c0b5f09faf 100644
--- a/lib/inets/src/http_server/httpd_response.erl
+++ b/lib/inets/src/http_server/httpd_response.erl
@@ -20,8 +20,8 @@
%%
-module(httpd_response).
-export([generate_and_send_response/1, send_status/3, send_header/3,
- send_body/3, send_chunk/3, send_final_chunk/2, split_header/2,
- is_disable_chunked_send/1, cache_headers/2]).
+ send_body/3, send_chunk/3, send_final_chunk/2, send_final_chunk/3,
+ split_header/2, is_disable_chunked_send/1, cache_headers/2]).
-export([map_status_code/2]).
-include_lib("inets/src/inets_app/inets_internal.hrl").
@@ -89,8 +89,7 @@ traverse_modules(ModData,[Module|Rest]) ->
"~n Error: ~p"
"~n Stack trace: ~p",
[Module, T, E, ?STACK()])),
- report_error(mod_log, ModData#mod.config_db, String),
- report_error(mod_disk_log, ModData#mod.config_db, String),
+ httpd_util:error_log(ModData#mod.config_db, String),
send_status(ModData, 500, none),
done
end.
@@ -245,7 +244,6 @@ send_chunk(_, <<>>, _) ->
ok;
send_chunk(_, [], _) ->
ok;
-
send_chunk(#mod{http_version = "HTTP/1.1",
socket_type = Type, socket = Sock}, Response0, false) ->
Response = http_chunk:encode(Response0),
@@ -254,10 +252,13 @@ send_chunk(#mod{http_version = "HTTP/1.1",
send_chunk(#mod{socket_type = Type, socket = Sock} = _ModData, Response, _) ->
httpd_socket:deliver(Type, Sock, Response).
+send_final_chunk(Mod, IsDisableChunkedSend) ->
+ send_final_chunk(Mod, [], IsDisableChunkedSend).
+
send_final_chunk(#mod{http_version = "HTTP/1.1",
- socket_type = Type, socket = Sock}, false) ->
- httpd_socket:deliver(Type, Sock, http_chunk:encode_last());
-send_final_chunk(#mod{socket_type = Type, socket = Sock}, _) ->
+ socket_type = Type, socket = Sock}, Trailers, false) ->
+ httpd_socket:deliver(Type, Sock, http_chunk:encode_last(Trailers));
+send_final_chunk(#mod{socket_type = Type, socket = Sock}, _, _) ->
httpd_socket:close(Type, Sock).
is_disable_chunked_send(Db) ->
@@ -397,16 +398,6 @@ send_response_old(#mod{socket_type = Type,
content_length(Body)->
integer_to_list(httpd_util:flatlength(Body)).
-report_error(Mod, ConfigDB, Error) ->
- Modules = httpd_util:lookup(ConfigDB, modules,
- [mod_get, mod_head, mod_log]),
- case lists:member(Mod, Modules) of
- true ->
- Mod:report_error(ConfigDB, Error);
- _ ->
- ok
- end.
-
handle_headers([], NewHeaders) ->
{ok, NewHeaders};
diff --git a/lib/inets/src/http_server/httpd_sup.erl b/lib/inets/src/http_server/httpd_sup.erl
index f0b1942e2f..bf40cedd5c 100644
--- a/lib/inets/src/http_server/httpd_sup.erl
+++ b/lib/inets/src/http_server/httpd_sup.erl
@@ -241,7 +241,7 @@ listen(Address, Port, Config) ->
case http_transport:start(SocketType) of
ok ->
{ok, Fd} = get_fd(Port),
- IpFamily = proplists:get_value(ipfamily, Config, inet6fb4),
+ IpFamily = proplists:get_value(ipfamily, Config, inet),
case http_transport:listen(SocketType, Address, Port, Fd, IpFamily) of
{ok, ListenSocket} ->
NewConfig = proplists:delete(port, Config),
@@ -286,6 +286,8 @@ socket_type(Config) ->
socket_type(ip_comm = SocketType, _) ->
SocketType;
+socket_type({ip_comm, _} = SocketType, _) ->
+ SocketType;
socket_type({essl, _} = SocketType, _) ->
SocketType;
socket_type(_, Config) ->
diff --git a/lib/inets/src/http_server/httpd_util.erl b/lib/inets/src/http_server/httpd_util.erl
index fc69baf829..ab43f0b378 100644
--- a/lib/inets/src/http_server/httpd_util.erl
+++ b/lib/inets/src/http_server/httpd_util.erl
@@ -31,7 +31,7 @@
convert_netscapecookie_date/1, enable_debug/1, valid_options/3,
modules_validate/1, module_validate/1,
dir_validate/2, file_validate/2, mime_type_validate/1,
- mime_types_validate/1, custom_date/0]).
+ mime_types_validate/1, custom_date/0, error_log/2]).
-export([encode_hex/1, decode_hex/1]).
-include_lib("kernel/include/file.hrl").
@@ -42,17 +42,7 @@ ip_address({_,_,_,_,_,_,_,_} = Address, _IpFamily) ->
{ok, Address};
ip_address(Host, IpFamily)
when ((IpFamily =:= inet) orelse (IpFamily =:= inet6)) ->
- inet:getaddr(Host, IpFamily);
-ip_address(Host, inet6fb4 = _IpFamily) ->
- Inet = case gen_tcp:listen(0, [inet6]) of
- {ok, Dummyport} ->
- gen_tcp:close(Dummyport),
- inet6;
- _ ->
- inet
- end,
- inet:getaddr(Host, Inet).
-
+ inet:getaddr(Host, IpFamily).
%% lookup
@@ -786,3 +776,17 @@ do_enable_debug([{Level,Modules}|Rest])
ok
end,
do_enable_debug(Rest).
+
+error_log(ConfigDb, Error) ->
+ error_log(mod_log, ConfigDb, Error),
+ error_log(mod_disk_log, ConfigDb, Error).
+
+error_log(Mod, ConfigDB, Error) ->
+ Modules = httpd_util:lookup(ConfigDB, modules,
+ [mod_get, mod_head, mod_log]),
+ case lists:member(Mod, Modules) of
+ true ->
+ Mod:report_error(ConfigDB, Error);
+ _ ->
+ ok
+ end.
diff --git a/lib/inets/src/http_server/mod_esi.erl b/lib/inets/src/http_server/mod_esi.erl
index b9a0797977..1923411449 100644
--- a/lib/inets/src/http_server/mod_esi.erl
+++ b/lib/inets/src/http_server/mod_esi.erl
@@ -376,7 +376,6 @@ erl_scheme_webpage_chunk(Mod, Func, Env, Input, ModData) ->
end),
Response = deliver_webpage_chunk(ModData, Pid),
-
process_flag(trap_exit,false),
Response.
@@ -418,7 +417,6 @@ deliver_webpage_chunk(#mod{config_db = Db} = ModData, Pid, Timeout) ->
?hdrv("deliver_webpage_chunk - timeout", []),
send_headers(ModData, 504, [{"connection", "close"}]),
httpd_socket:close(ModData#mod.socket_type, ModData#mod.socket),
- process_flag(trap_exit,false),
{proceed,[{response, {already_sent, 200, 0}} | ModData#mod.data]}
end.
@@ -446,7 +444,6 @@ send_headers(ModData, StatusCode, HTTPHeaders) ->
ExtraHeaders ++ HTTPHeaders).
handle_body(_, #mod{method = "HEAD"} = ModData, _, _, Size, _) ->
- process_flag(trap_exit,false),
{proceed, [{response, {already_sent, 200, Size}} | ModData#mod.data]};
handle_body(Pid, ModData, Body, Timeout, Size, IsDisableChunkedSend) ->
@@ -454,34 +451,54 @@ handle_body(Pid, ModData, Body, Timeout, Size, IsDisableChunkedSend) ->
httpd_response:send_chunk(ModData, Body, IsDisableChunkedSend),
receive
{esi_data, Data} when is_binary(Data) ->
- ?hdrt("handle_body - received binary data (esi)", []),
handle_body(Pid, ModData, Data, Timeout, Size + byte_size(Data),
IsDisableChunkedSend);
{esi_data, Data} ->
- ?hdrt("handle_body - received data (esi)", []),
handle_body(Pid, ModData, Data, Timeout, Size + length(Data),
IsDisableChunkedSend);
{ok, Data} ->
- ?hdrt("handle_body - received data (ok)", []),
handle_body(Pid, ModData, Data, Timeout, Size + length(Data),
IsDisableChunkedSend);
{'EXIT', Pid, normal} when is_pid(Pid) ->
- ?hdrt("handle_body - exit:normal", []),
httpd_response:send_final_chunk(ModData, IsDisableChunkedSend),
{proceed, [{response, {already_sent, 200, Size}} |
ModData#mod.data]};
{'EXIT', Pid, Reason} when is_pid(Pid) ->
- ?hdrv("handle_body - exit", [{reason, Reason}]),
- httpd_response:send_final_chunk(ModData, IsDisableChunkedSend),
- exit({mod_esi_linked_process_died, Pid, Reason})
-
+ Error = lists:flatten(io_lib:format("mod_esi process failed with reason ~p", [Reason])),
+ httpd_util:error_log(ModData#mod.config_db, Error),
+ httpd_response:send_final_chunk(ModData,
+ [{"Warning", "199 inets server - body maybe incomplete, "
+ "internal server error"}],
+ IsDisableChunkedSend),
+ done
after Timeout ->
- ?hdrv("handle_body - timeout", []),
- process_flag(trap_exit,false),
- httpd_response:send_final_chunk(ModData, IsDisableChunkedSend),
- exit({mod_esi_linked_process_timeout, Pid})
+ kill_esi_delivery_process(Pid),
+ httpd_response:send_final_chunk(ModData, [{"Warning", "199 inets server - "
+ "body maybe incomplete, timed out"}],
+ IsDisableChunkedSend),
+ done
end.
+kill_esi_delivery_process(Pid) ->
+ exit(Pid, kill),
+ receive
+ {'EXIT', Pid, killed} ->
+ %% Clean message queue
+ receive
+ {esi_data, _} ->
+ ok
+ after 0 ->
+ ok
+ end,
+ receive
+ {ok, _} ->
+ ok
+ after 0 ->
+ ok
+ end
+ end.
+
+
erl_script_timeout(Db) ->
httpd_util:lookup(Db, erl_script_timeout, ?DEFAULT_ERL_TIMEOUT).
diff --git a/lib/inets/src/inets_app/inets.app.src b/lib/inets/src/inets_app/inets.app.src
index 2b9b8f5f32..883ba84e8e 100644
--- a/lib/inets/src/inets_app/inets.app.src
+++ b/lib/inets/src/inets_app/inets.app.src
@@ -65,6 +65,7 @@
httpd_connection_sup,
httpd_conf,
httpd_custom,
+ httpd_custom_api,
httpd_esi,
httpd_example,
httpd_file,
diff --git a/lib/inets/test/http_format_SUITE.erl b/lib/inets/test/http_format_SUITE.erl
index a97b51601f..e977bd1b9b 100644
--- a/lib/inets/test/http_format_SUITE.erl
+++ b/lib/inets/test/http_format_SUITE.erl
@@ -20,26 +20,12 @@
%%
-module(http_format_SUITE).
--author('[email protected]').
-include_lib("common_test/include/ct.hrl").
--include("test_server_line.hrl").
-include("http_internal.hrl").
-%% Test server specific exports
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2, init_per_testcase/2, end_per_testcase/2]).
-
-%% Test cases must be exported.
--export([ chunk_decode/1, chunk_encode/1,
- chunk_extensions_otp_6005/1, chunk_decode_otp_6264/1,
- chunk_decode_empty_chunk_otp_6511/1,
- chunk_decode_trailer/1,
- http_response/1, http_request/1, validate_request_line/1,
- esi_parse_headers/1, cgi_parse_headers/1,
- is_absolut_uri/1, convert_netscapecookie_date/1,
- check_content_length_encoding/1]).
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
all() ->
[{group, chunk}, http_response, http_request,
@@ -52,7 +38,8 @@ groups() ->
[chunk_decode, chunk_encode, chunk_extensions_otp_6005,
chunk_decode_otp_6264,
chunk_decode_empty_chunk_otp_6511,
- chunk_decode_trailer]}].
+ chunk_whitespace_suffix,
+ chunk_decode_trailer, chunk_max_headersize, chunk_max_bodysize, chunk_not_hex]}].
init_per_suite(Config) ->
Config.
@@ -81,12 +68,8 @@ end_per_testcase(_, Config) ->
%% Test cases starts here.
%%-------------------------------------------------------------------------
-
-%%-------------------------------------------------------------------------
-chunk_decode(doc) ->
- ["Test http_chunk:decode/3"];
-chunk_decode(suite) ->
- [];
+chunk_decode() ->
+ [{doc, "Test http_chunk:decode/3"}].
chunk_decode(Config) when is_list(Config) ->
ReqHeaders = #http_request_h{'transfer-encoding' = "chunked"},
ChunkedBody = "A" ++ ?CRLF ++ "1234567890" ++ ?CRLF ++ "4" ++
@@ -109,15 +92,11 @@ chunk_decode(Config) when is_list(Config) ->
?HTTP_MAX_BODY_SIZE, ?HTTP_MAX_HEADER_SIZE),
{_, Body} = parse(Module, Function, Args, tl(NewChunkedBody)),
- "1234567890HEJ!" = binary_to_list(Body),
-
- ok.
+ "1234567890HEJ!" = binary_to_list(Body).
%%-------------------------------------------------------------------------
-chunk_extensions_otp_6005(doc) ->
- ["Make sure so called extensions are ignored"];
-chunk_extensions_otp_6005(suite) ->
- [];
+chunk_extensions_otp_6005() ->
+ [{doc, "Make sure so called extensions are ignored"}].
chunk_extensions_otp_6005(Config) when is_list(Config)->
ChunkedBody = "A;ignore this" ++ ?CRLF ++ "1234567890" ++
?CRLF ++ "4" ++ ?CRLF ++ "HEJ!"++ ?CRLF ++ "0" ++
@@ -136,14 +115,11 @@ chunk_extensions_otp_6005(Config) when is_list(Config)->
?HTTP_MAX_BODY_SIZE, ?HTTP_MAX_HEADER_SIZE),
{_, NewBody} = parse(Module1, Function1, Args1, tl(ChunkedBody1)),
- "1234567890HEJ!" = binary_to_list(NewBody),
- ok.
+ "1234567890HEJ!" = binary_to_list(NewBody).
%%-------------------------------------------------------------------------
-chunk_decode_otp_6264(doc) ->
- ["Check that 0 in the body does not count as the last chunk"];
-chunk_decode_otp_6264(suite) ->
- [];
+chunk_decode_otp_6264() ->
+ [{doc, "Check that 0 in the body does not count as the last chunk"}].
chunk_decode_otp_6264(Config) when is_list(Config)->
ChunkedBody = "A;ignore this" ++ ?CRLF ++ "1234567890" ++
?CRLF ++ "4" ++ ?CRLF ++ "0123"++ ?CRLF ++ "0" ++
@@ -173,27 +149,33 @@ chunk_decode_otp_6264(Config) when is_list(Config)->
?HTTP_MAX_BODY_SIZE, ?HTTP_MAX_HEADER_SIZE),
{_, NewBody} = parse(Module1, Function1, Args1, tl(NewChunkedBody1)),
- "12345678900" = binary_to_list(NewBody),
-
- ok.
+ "12345678900" = binary_to_list(NewBody).
%%-------------------------------------------------------------------------
-chunk_decode_empty_chunk_otp_6511(doc) ->
- [""];
-chunk_decode_empty_chunk_otp_6511(suite) ->
- [];
chunk_decode_empty_chunk_otp_6511(Config) when is_list(Config) ->
ChunkedBody = "0" ++ ?CRLF ++ ?CRLF,
{ok,{["content-length:0"],<<>>}} =
http_chunk:decode(list_to_binary(ChunkedBody),
- ?HTTP_MAX_BODY_SIZE, ?HTTP_MAX_HEADER_SIZE),
- ok.
+ ?HTTP_MAX_BODY_SIZE, ?HTTP_MAX_HEADER_SIZE).
%%-------------------------------------------------------------------------
-chunk_decode_trailer(doc) ->
- ["Make sure trailers are handled correctly. Trailers should"
- "become new headers"];
-chunk_decode_trailer(suite) ->
- [];
+chunk_whitespace_suffix() ->
+ [{doc, "Test whitespace after chunked length header"}].
+chunk_whitespace_suffix(Config) when is_list(Config) ->
+ ChunkedBody = "1a ; ignore-stuff-here" ++ ?CRLF ++
+ "abcdefghijklmnopqrstuvwxyz" ++ ?CRLF ++ "10 " ++ ?CRLF
+ ++ "1234567890abcdef" ++ ?CRLF ++ "0 " ++ ?CRLF
+ ++ "some-footer:some-value" ++ ?CRLF
+ ++ "another-footer:another-value" ++ ?CRLF ++ ?CRLF,
+ {ok, {["content-length:42", "another-footer:another-value",
+ "some-footer:some-value", ""],
+ <<"abcdefghijklmnopqrstuvwxyz1234567890abcdef">>}} =
+ http_chunk:decode(list_to_binary(ChunkedBody),
+ ?HTTP_MAX_BODY_SIZE, ?HTTP_MAX_HEADER_SIZE).
+
+%%-------------------------------------------------------------------------
+chunk_decode_trailer() ->
+ [{doc,"Make sure trailers are handled correctly. Trailers should"
+ "become new headers"}].
chunk_decode_trailer(Config) when is_list(Config)->
ChunkedBody = "1a; ignore-stuff-here" ++ ?CRLF ++
"abcdefghijklmnopqrstuvwxyz" ++ ?CRLF ++ "10" ++ ?CRLF
@@ -249,30 +231,79 @@ chunk_decode_trailer(Config) when is_list(Config)->
?HTTP_MAX_BODY_SIZE, ?HTTP_MAX_HEADER_SIZE),
{_, NewBody} = parse(Module1, Function1, Args1, tl(ChunkedBody3)),
- "abcdefghijklmnopqrstuvwxyz1234567890abcdef" = binary_to_list(NewBody),
-
- ok.
+ "abcdefghijklmnopqrstuvwxyz1234567890abcdef" = binary_to_list(NewBody).
%%-------------------------------------------------------------------------
-chunk_encode(doc) ->
- ["Test http_chunk:encode/1 & http_chunk:encode_last/0"];
-chunk_encode(suite) ->
- [];
+chunk_encode() ->
+ [{doc, "Test http_chunk:encode/1 & http_chunk:encode_last/0"}].
chunk_encode(Config) when is_list(Config) ->
<<54, ?CR, ?LF, 102,111,111,98,97,114, ?CR, ?LF>> =
http_chunk:encode(list_to_binary("foobar")),
["6", ?CR, ?LF,"foobar", ?CR, ?LF] = http_chunk:encode("foobar"),
- <<$0, ?CR, ?LF, ?CR, ?LF >> = http_chunk:encode_last(),
- ok.
-
+ <<$0, ?CR, ?LF, ?CR, ?LF >> = http_chunk:encode_last().
+%%-------------------------------------------------------------------------
+chunk_max_headersize() ->
+ [{doc, "Test max header limit"}].
+chunk_max_headersize(Config) when is_list(Config) ->
+ ChunkedBody = "1a; ignore-stuff-here" ++ ?CRLF ++
+ "abcdefghijklmnopqrstuvwxyz" ++ ?CRLF ++ "10" ++ ?CRLF
+ ++ "1234567890abcdef" ++ ?CRLF ++ "0" ++ ?CRLF
+ ++ "some-footer:some-value" ++ ?CRLF
+ ++ "another-footer:another-value" ++ ?CRLF ++ ?CRLF,
+
+ {ok, {_, _}} =
+ http_chunk:decode(list_to_binary(ChunkedBody),
+ ?HTTP_MAX_BODY_SIZE, ?HTTP_MAX_HEADER_SIZE),
+
+ %% Too long in length header
+ {error,{header_too_long, {max, 1}}} =
+ (catch http_chunk:decode(list_to_binary(ChunkedBody),
+ ?HTTP_MAX_BODY_SIZE, 1)),
+
+ %% Too long in extension field
+ {error,{header_too_long, {max, 10}}} =
+ (catch http_chunk:decode(list_to_binary(ChunkedBody),
+ ?HTTP_MAX_BODY_SIZE, 10)),
+
+ %% Too long in trailer
+ {error,{header_too_long, {max, 30}}} =
+ (catch http_chunk:decode(list_to_binary(ChunkedBody),
+ ?HTTP_MAX_BODY_SIZE, 30)).
+%%-------------------------------------------------------------------------
+chunk_not_hex() ->
+ [{doc, "Test bad chunked length header"}].
+chunk_not_hex(Config) when is_list(Config) ->
+ ChunkedBody = "åäö; ignore-stuff-here" ++ ?CRLF ++
+ "abcdefghijklmnopqrstuvwxyz" ++ ?CRLF ++ "10" ++ ?CRLF
+ ++ "1234567890abcdef" ++ ?CRLF ++ "0" ++ ?CRLF
+ ++ "some-footer:some-value" ++ ?CRLF
+ ++ "another-footer:another-value" ++ ?CRLF ++ ?CRLF,
+ {error,{chunk_size, "åäö"}} =
+ (catch http_chunk:decode(list_to_binary(ChunkedBody),
+ ?HTTP_MAX_BODY_SIZE, ?HTTP_MAX_HEADER_SIZE)).
+%%-------------------------------------------------------------------------
+chunk_max_bodysize() ->
+ [{doc, "Test max body limit"}].
+chunk_max_bodysize(Config) when is_list(Config) ->
+ ChunkedBody = "1a; ignore-stuff-here" ++ ?CRLF ++
+ "abcdefghijklmnopqrstuvwxyz" ++ ?CRLF ++ "10" ++ ?CRLF
+ ++ "1234567890abcdef" ++ ?CRLF ++ "0" ++ ?CRLF
+ ++ "some-footer:some-value" ++ ?CRLF
+ ++ "another-footer:another-value" ++ ?CRLF ++ ?CRLF,
+ {ok, {_, _}} =
+ http_chunk:decode(list_to_binary(ChunkedBody),
+ ?HTTP_MAX_BODY_SIZE, ?HTTP_MAX_HEADER_SIZE),
+
+ %% Too long body
+ {error,{body_too_big, {max, 10}}} =
+ (catch http_chunk:decode(list_to_binary(ChunkedBody),
+ 10, ?HTTP_MAX_HEADER_SIZE)).
%%-------------------------------------------------------------------------
-http_response(doc) ->
- ["Test httpc_response:parse*. This test case will simulate that the "
+http_response() ->
+ [{doc, "Test httpc_response:parse*. This test case will simulate that the "
"message will be recived a little at the time on a socket and the "
- "package may be broken up into smaller parts at arbitrary point."];
-http_response(suite) ->
- [];
+ "package may be broken up into smaller parts at arbitrary point."}].
http_response(Config) when is_list(Config) ->
HttpHead1 = ["HTTP", "/1.1 ", "20", "0 ", "ok", [?CR, ?LF],
@@ -340,12 +371,10 @@ http_response(Config) when is_list(Config) ->
[<<>>,Length1], HttpBody1)),
ok.
%%-------------------------------------------------------------------------
-http_request(doc) ->
- ["Test httpd_request:parse* This test case will simulate that the "
+http_request() ->
+ [{doc, "Test httpd_request:parse* This test case will simulate that the "
"message will be recived a little at the time on a socket and the "
- "package may be broken up into smaller parts at arbitrary point."];
-http_request(suite) ->
- [];
+ "package may be broken up into smaller parts at arbitrary point."}].
http_request(Config) when is_list(Config) ->
HttpHead = ["GE", "T ", "http://www.erlang", ".org ", "HTTP",
@@ -407,15 +436,12 @@ http_request(Config) when is_list(Config) ->
NewBody1 =
binary_to_list(parse
(httpd_request, whole_body,
- [<<>>, Length1], HttpBody1)),
- ok.
+ [<<>>, Length1], HttpBody1)).
%%-------------------------------------------------------------------------
-validate_request_line(doc) ->
- ["Test httpd_request:validate/3. Makes sure you can not get past"
+validate_request_line() ->
+ [{doc, "Test httpd_request:validate/3. Makes sure you can not get past"
" the server_root and that the request is recognized by the server"
- " and protcol version." ];
-validate_request_line(suite) ->
- [];
+ " and protcol version."}].
validate_request_line(Config) when is_list(Config) ->
%% HTTP/0.9 only has GET requests
@@ -468,16 +494,12 @@ validate_request_line(Config) when is_list(Config) ->
NewForbiddenUri1 =
"http://127.0.0.1:8888/../home/ingela/test.html",
{error, {bad_request, {forbidden, NewForbiddenUri1}}} =
- httpd_request:validate("GET", NewForbiddenUri1, "HTTP/1.1"),
-
- ok.
+ httpd_request:validate("GET", NewForbiddenUri1, "HTTP/1.1").
%%-------------------------------------------------------------------------
-check_content_length_encoding(doc) ->
- ["Test http_request:headers/2. Check that the content-length is"
- " encoded even when it is zero." ];
-check_content_length_encoding(suite) ->
- [];
+check_content_length_encoding() ->
+ [{doc, "Test http_request:headers/2. Check that the content-length is"
+ " encoded even when it is zero."}].
check_content_length_encoding(Config) when is_list(Config) ->
%% Check that the content-length is preserved.
@@ -486,16 +508,12 @@ check_content_length_encoding(Config) when is_list(Config) ->
true = (string:str(Header1, "content-length: 123\r\n") > 0),
%% Check that content-length=0 is handled correctly.
Header2 = http_request:http_headers(#http_request_h{'content-length'="0"}),
- true = (string:str(Header2, "content-length: 0\r\n") > 0),
-
- ok.
+ true = (string:str(Header2, "content-length: 0\r\n") > 0).
%%-------------------------------------------------------------------------
-esi_parse_headers(doc) ->
- ["Test httpd_esi:*. All header values are received in the same"
- " erlang message."];
-esi_parse_headers(suite) ->
- [];
+esi_parse_headers() ->
+ [{doc, "Test httpd_esi:*. All header values are received in the same"
+ " erlang message."}].
esi_parse_headers(Config) when is_list(Config) ->
ESIResult = "content-type:text/html\r\ndate:Thu, 28 Oct 2004 07:57:43 "
@@ -522,16 +540,14 @@ esi_parse_headers(Config) when is_list(Config) ->
httpd_esi:handle_headers(Headers2),
{proceed,"/foo/bar.html"} =
- httpd_esi:handle_headers("location:/foo/bar.html\r\n"),
- ok.
+ httpd_esi:handle_headers("location:/foo/bar.html\r\n").
%%--------------------------------------------------------------------
-cgi_parse_headers(doc) ->
- ["Test httpd_cgi:*. This test case will simulate that the "
+cgi_parse_headers() ->
+ [{doc, "Test httpd_cgi:*. This test case will simulate that the "
"message will be recived a little at the time on a socket and the "
- "package may be broken up into smaller parts at arbitrary point."];
-cgi_parse_headers(suite) ->
- [];
+ "package may be broken up into smaller parts at arbitrary point."}].
+
cgi_parse_headers(Config) when is_list(Config) ->
CGIResult = ["content-type:text", "/html\ndate:Thu, 28 Oct 2004 07:57:43 "
@@ -567,26 +583,18 @@ cgi_parse_headers(Config) when is_list(Config) ->
{ok,[{"content-type","text/html"},
{"connection","close"},
{"content-language","en"},
- {"age","4711"}], {200,"ok"}} = httpd_cgi:handle_headers(Headers3),
-
- ok.
-
+ {"age","4711"}], {200,"ok"}} = httpd_cgi:handle_headers(Headers3).
%%-------------------------------------------------------------------------
-is_absolut_uri(doc) ->
- ["Test http_request:is_absolut_uri/1."];
-is_absolut_uri(suite) ->
- [];
+is_absolut_uri() ->
+ [{doc, "Test http_request:is_absolut_uri/1."}].
is_absolut_uri(Config) when is_list(Config) ->
true = http_request:is_absolut_uri("http://www.erlang.org"),
true = http_request:is_absolut_uri("https://www.erlang.org"),
false = http_request:is_absolut_uri("index.html").
-
%%-------------------------------------------------------------------------
-convert_netscapecookie_date(doc) ->
- ["Test http_util:convert_netscapecookie_date/1."];
-convert_netscapecookie_date(suite) ->
- [];
+convert_netscapecookie_date() ->
+ [{doc, "Test http_util:convert_netscapecookie_date/1."}].
convert_netscapecookie_date(Config) when is_list(Config) ->
{{2006,1,6},{8,59,38}} =
http_util:convert_netscapecookie_date("Mon, 06-Jan-2006 08:59:38 GMT"),
@@ -619,9 +627,7 @@ convert_netscapecookie_date(Config) when is_list(Config) ->
{{2006,12,12},{8,59,38}} =
http_util:convert_netscapecookie_date("Sun 12-Dec-06 08:59:38 GMT"),
{{2036,1,1},{8,0,1}} =
- http_util:convert_netscapecookie_date("Tue Jan 01 08:00:01 2036 GMT"),
- ok.
-
+ http_util:convert_netscapecookie_date("Tue Jan 01 08:00:01 2036 GMT").
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
diff --git a/lib/inets/test/httpc_SUITE.erl b/lib/inets/test/httpc_SUITE.erl
index 2ad00bdf76..c6c59ab1af 100644
--- a/lib/inets/test/httpc_SUITE.erl
+++ b/lib/inets/test/httpc_SUITE.erl
@@ -98,12 +98,15 @@ only_simulated() ->
stream_once,
stream_single_chunk,
stream_no_length,
+ not_streamed_once,
+ stream_large_not_200_or_206,
no_content_204,
tolerate_missing_CR,
userinfo,
bad_response,
internal_server_error,
invalid_http,
+ invalid_chunk_size,
headers_dummy,
headers_with_obs_fold,
empty_response_header,
@@ -408,6 +411,21 @@ stream_no_length(Config) when is_list(Config) ->
stream_test(Request1, {stream, self}),
Request2 = {url(group_name(Config), "/http_1_0_no_length_multiple.html", Config), []},
stream_test(Request2, {stream, self}).
+%%-------------------------------------------------------------------------
+stream_large_not_200_or_206() ->
+ [{doc, "Test the option stream for large responses with status codes "
+ "other than 200 or 206" }].
+stream_large_not_200_or_206(Config) when is_list(Config) ->
+ Request = {url(group_name(Config), "/large_404_response.html", Config), []},
+ {404, _} = not_streamed_test(Request, {stream, self}).
+%%-------------------------------------------------------------------------
+not_streamed_once() ->
+ [{doc, "Test not streamed responses with once streaming"}].
+not_streamed_once(Config) when is_list(Config) ->
+ Request0 = {url(group_name(Config), "/404.html", Config), []},
+ {404, _} = not_streamed_test(Request0, {stream, {self, once}}),
+ Request1 = {url(group_name(Config), "/404_chunked.html", Config), []},
+ {404, _} = not_streamed_test(Request1, {stream, {self, once}}).
%%-------------------------------------------------------------------------
@@ -748,6 +766,22 @@ invalid_http(Config) when is_list(Config) ->
ct:print("Parse error: ~p ~n", [Reason]).
%%-------------------------------------------------------------------------
+
+invalid_chunk_size(doc) ->
+ ["Test parse error of HTTP chunk size"];
+invalid_chunk_size(suite) ->
+ [];
+invalid_chunk_size(Config) when is_list(Config) ->
+
+ URL = url(group_name(Config), "/invalid_chunk_size.html", Config),
+
+ {error, {chunk_size, _} = Reason} =
+ httpc:request(get, {URL, []}, [], []),
+
+ ct:print("Parse error: ~p ~n", [Reason]).
+
+%%-------------------------------------------------------------------------
+
emulate_lower_versions(doc) ->
[{doc, "Perform request as 0.9 and 1.0 clients."}];
emulate_lower_versions(Config) when is_list(Config) ->
@@ -1117,6 +1151,19 @@ stream_test(Request, To) ->
Body = binary_to_list(StreamedBody).
+not_streamed_test(Request, To) ->
+ {ok, {{_,Code,_}, [_ | _], Body}} =
+ httpc:request(get, Request, [], [{body_format, binary}]),
+ {ok, RequestId} =
+ httpc:request(get, Request, [], [{body_format, binary}, {sync, false}, To]),
+
+ receive
+ {http, {RequestId, {{_, Code, _}, _Headers, Body}}} ->
+ {Code, binary_to_list(Body)};
+ {http, Msg} ->
+ ct:fail(Msg)
+ end.
+
url(http, End, Config) ->
Port = ?config(port, Config),
{ok,Host} = inet:gethostname(),
@@ -1648,6 +1695,11 @@ handle_uri(_,"/307.html",Port,_,Socket,_) ->
"Content-Length:" ++ integer_to_list(length(Body))
++ "\r\n\r\n" ++ Body;
+handle_uri(_,"/404.html",_,_,_,_) ->
+ "HTTP/1.1 404 not found\r\n" ++
+ "Content-Length:14\r\n\r\n" ++
+ "Page not found";
+
handle_uri(_,"/500.html",_,_,_,_) ->
"HTTP/1.1 500 Internal Server Error\r\n" ++
"Content-Length:47\r\n\r\n" ++
@@ -1783,6 +1835,15 @@ handle_uri(_,"/once_chunked.html",_,_,Socket,_) ->
http_chunk:encode("obar</BODY></HTML>")),
http_chunk:encode_last();
+handle_uri(_,"/404_chunked.html",_,_,Socket,_) ->
+ Head = "HTTP/1.1 404 not found\r\n" ++
+ "Transfer-Encoding:Chunked\r\n\r\n",
+ send(Socket, Head),
+ send(Socket, http_chunk:encode("<HTML><BODY>Not ")),
+ send(Socket,
+ http_chunk:encode("found</BODY></HTML>")),
+ http_chunk:encode_last();
+
handle_uri(_,"/single_chunk.html",_,_,Socket,_) ->
Chunk = "HTTP/1.1 200 ok\r\n" ++
"Transfer-Encoding:Chunked\r\n\r\n" ++
@@ -1807,6 +1868,17 @@ handle_uri(_,"/http_1_0_no_length_multiple.html",_,_,Socket,_) ->
send(Socket, string:copies("other multiple packets ", 200)),
close(Socket);
+handle_uri(_,"/large_404_response.html",_,_,Socket,_) ->
+ %% long body to make sure it will be sent in multiple tcp packets
+ Body = string:copies("other multiple packets ", 200),
+ Head = io_lib:format("HTTP/1.1 404 not found\r\n"
+ "Content-length: ~B\r\n"
+ "Content-type: text/plain\r\n\r\n",
+ [length(Body)]),
+ send(Socket, Head),
+ send(Socket, Body),
+ close(Socket);
+
handle_uri(_,"/once.html",_,_,Socket,_) ->
Head = "HTTP/1.1 200 ok\r\n" ++
"Content-Length:32\r\n\r\n",
@@ -1821,6 +1893,10 @@ handle_uri(_,"/invalid_http.html",_,_,_,_) ->
"HTTP/1.1 301\r\nDate:Sun, 09 Dec 2007 13:04:18 GMT\r\n" ++
"Transfer-Encoding:chunked\r\n\r\n";
+handle_uri(_,"/invalid_chunk_size.html",_,_,_,_) ->
+ "HTTP/1.1 200 ok\r\n" ++
+ "Transfer-Encoding:chunked\r\n\r\nåäö\r\n";
+
handle_uri(_,"/missing_reason_phrase.html",_,_,_,_) ->
"HTTP/1.1 200\r\n" ++
"Content-Length: 32\r\n\r\n"
diff --git a/lib/inets/test/httpd_1_1.erl b/lib/inets/test/httpd_1_1.erl
index dd9d21bbfc..db6def9d17 100644
--- a/lib/inets/test/httpd_1_1.erl
+++ b/lib/inets/test/httpd_1_1.erl
@@ -24,7 +24,7 @@
-include_lib("kernel/include/file.hrl").
-export([host/4, chunked/4, expect/4, range/4, if_test/5, trace/4,
- head/4, mod_cgi_chunked_encoding_test/5]).
+ head/4, mod_cgi_chunked_encoding_test/5, mod_esi_chunk_timeout/4]).
%% -define(all_keys_lower_case,true).
-ifndef(all_keys_lower_case).
@@ -274,6 +274,15 @@ mod_cgi_chunked_encoding_test(Type, Port, Host, Node, [Request| Rest])->
[{statuscode, 200}]),
mod_cgi_chunked_encoding_test(Type, Port, Host, Node, Rest).
+
+mod_esi_chunk_timeout(Type, Port, Host, Node) ->
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "GET /cgi-bin/erl/httpd_example/chunk_timeout?input=20000 HTTP/1.1\r\n"
+ "Host:"++ Host ++"\r\n"
+ "\r\n",
+ [{statuscode, 200},
+ {header, "warning"}]).
+
%%--------------------------------------------------------------------
%% Internal functions
%%--------------------------------------------------------------------
diff --git a/lib/inets/test/httpd_SUITE.erl b/lib/inets/test/httpd_SUITE.erl
index b50d31a5c1..1d8a603981 100644
--- a/lib/inets/test/httpd_SUITE.erl
+++ b/lib/inets/test/httpd_SUITE.erl
@@ -117,7 +117,7 @@ groups() ->
{htaccess, [], [htaccess_1_1, htaccess_1_0, htaccess_0_9]},
{security, [], [security_1_1, security_1_0]}, %% Skip 0.9 as causes timing issus in test code
{http_1_1, [], [host, chunked, expect, cgi, cgi_chunked_encoding_test,
- trace, range, if_modified_since] ++ http_head() ++ http_get() ++ load()},
+ trace, range, if_modified_since, mod_esi_chunk_timeout] ++ http_head() ++ http_get() ++ load()},
{http_1_0, [], [host, cgi, trace] ++ http_head() ++ http_get() ++ load()},
{http_0_9, [], http_head() ++ http_get() ++ load()}
].
@@ -757,6 +757,13 @@ esi(Config) when is_list(Config) ->
Config, [{statuscode, 200},
{no_header, "cache-control"}]).
%%-------------------------------------------------------------------------
+mod_esi_chunk_timeout(Config) when is_list(Config) ->
+ ok = httpd_1_1:mod_esi_chunk_timeout(?config(type, Config),
+ ?config(port, Config),
+ ?config(host, Config),
+ ?config(node, Config)).
+
+%%-------------------------------------------------------------------------
cgi() ->
[{doc, "Test mod_cgi"}].
@@ -1434,9 +1441,11 @@ server_config(http_reload, Config) ->
server_config(https_reload, Config) ->
[{keep_alive_timeout, 2}] ++ server_config(https, Config);
server_config(http_limit, Config) ->
- [{max_clients, 1},
- %% Make sure option checking code is run
- {max_content_length, 100000002}] ++ server_config(http, Config);
+ Conf = [{max_clients, 1},
+ %% Make sure option checking code is run
+ {max_content_length, 100000002}] ++ server_config(http, Config),
+ ct:pal("Received message ~p~n", [Conf]),
+ Conf;
server_config(http_custom, Config) ->
[{customize, ?MODULE}] ++ server_config(http, Config);
server_config(https_custom, Config) ->
@@ -1486,6 +1495,7 @@ server_config(http_mime_types, Config0) ->
server_config(http, Config) ->
ServerRoot = ?config(server_root, Config),
[{port, 0},
+ {socket_type, {ip_comm, [{nodelay, true}]}},
{server_name,"httpd_test"},
{server_root, ServerRoot},
{document_root, ?config(doc_root, Config)},
@@ -1507,13 +1517,14 @@ server_config(http, Config) ->
server_config(https, Config) ->
PrivDir = ?config(priv_dir, Config),
[{socket_type, {essl,
- [{cacertfile,
- filename:join(PrivDir, "public_key_cacert.pem")},
- {certfile,
- filename:join(PrivDir, "public_key_cert.pem")},
- {keyfile,
- filename:join(PrivDir, "public_key_cert_key.pem")}
- ]}}] ++ server_config(http, Config).
+ [{nodelay, true},
+ {cacertfile,
+ filename:join(PrivDir, "public_key_cacert.pem")},
+ {certfile,
+ filename:join(PrivDir, "public_key_cert.pem")},
+ {keyfile,
+ filename:join(PrivDir, "public_key_cert_key.pem")}
+ ]}}] ++ proplists:delete(socket_type, server_config(http, Config)).
init_httpd(Group, Config0) ->
Config1 = proplists:delete(port, Config0),
diff --git a/lib/inets/test/httpd_SUITE_data/Makefile.src b/lib/inets/test/httpd_SUITE_data/Makefile.src
index b0fdb43d8d..cea40dd8cb 100644
--- a/lib/inets/test/httpd_SUITE_data/Makefile.src
+++ b/lib/inets/test/httpd_SUITE_data/Makefile.src
@@ -10,5 +10,10 @@ all: $(PROGS)
cgi_echo@exe@: cgi_echo@obj@
$(LD) $(CROSSLDFLAGS) -o cgi_echo cgi_echo@obj@ @LIBS@
+@IFEQ@ (@CC@, cl -nologo)
+cgi_echo@obj@: cgi_echo.c
+ $(CC) /c /Focgi_echo@obj@ $(CFLAGS) cgi_echo.c
+@ELSE@
cgi_echo@obj@: cgi_echo.c
$(CC) -c -o cgi_echo@obj@ $(CFLAGS) cgi_echo.c
+@ENDIF@
diff --git a/lib/inets/test/httpd_test_lib.erl b/lib/inets/test/httpd_test_lib.erl
index a5b836f651..c58966ce10 100644
--- a/lib/inets/test/httpd_test_lib.erl
+++ b/lib/inets/test/httpd_test_lib.erl
@@ -235,11 +235,17 @@ validate(RequestStr, #state{status_line = {Version, StatusCode, _},
_ ->
ok
end,
- do_validate(http_response:header_list(Headers), Options, N, P),
- check_body(RequestStr, StatusCode,
- Headers#http_response_h.'content-type',
- list_to_integer(Headers#http_response_h.'content-length'),
- Body).
+ HList = http_response:header_list(Headers),
+ do_validate(HList, Options, N, P),
+ case lists:keysearch("warning", 1, HList) of
+ {value, _} ->
+ ok;
+ _ ->
+ check_body(RequestStr, StatusCode,
+ Headers#http_response_h.'content-type',
+ list_to_integer(Headers#http_response_h.'content-length'),
+ Body)
+ end.
%--------------------------------------------------------------------
%% Internal functions
diff --git a/lib/inets/vsn.mk b/lib/inets/vsn.mk
index 480caeca4b..7cc95fa6d3 100644
--- a/lib/inets/vsn.mk
+++ b/lib/inets/vsn.mk
@@ -19,6 +19,6 @@
# %CopyrightEnd%
APPLICATION = inets
-INETS_VSN = 6.0.2
+INETS_VSN = 6.0.3
PRE_VSN =
APP_VSN = "$(APPLICATION)-$(INETS_VSN)$(PRE_VSN)"
diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangMap.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangMap.java
index 0fd7d3ce37..30126db3fd 100644
--- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangMap.java
+++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangMap.java
@@ -19,7 +19,7 @@
*/
package com.ericsson.otp.erlang;
-import java.util.HashMap;
+import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
@@ -37,13 +37,22 @@ public class OtpErlangMap extends OtpErlangObject {
// don't change this!
private static final long serialVersionUID = -6410770117696198497L;
- private HashMap<OtpErlangObject, OtpErlangObject> map;
+ private OtpMap map;
+
+ private static class OtpMap
+ extends LinkedHashMap<OtpErlangObject, OtpErlangObject> {
+ private static final long serialVersionUID = -2666505810905455082L;
+
+ public OtpMap() {
+ super();
+ }
+ }
/**
* Create an empty map.
*/
public OtpErlangMap() {
- map = new HashMap<OtpErlangObject, OtpErlangObject>();
+ map = new OtpMap();
}
/**
@@ -93,7 +102,7 @@ public class OtpErlangMap extends OtpErlangObject {
throw new java.lang.IllegalArgumentException(
"Map keys and values must have same arity");
}
- map = new HashMap<OtpErlangObject, OtpErlangObject>(vcount);
+ map = new OtpMap();
OtpErlangObject key, val;
for (int i = 0; i < vcount; i++) {
if ((key = keys[kstart + i]) == null) {
@@ -125,7 +134,7 @@ public class OtpErlangMap extends OtpErlangObject {
final int arity = buf.read_map_head();
if (arity > 0) {
- map = new HashMap<OtpErlangObject, OtpErlangObject>(arity);
+ map = new OtpMap();
for (int i = 0; i < arity; i++) {
OtpErlangObject key, val;
key = buf.read_any();
@@ -133,7 +142,7 @@ public class OtpErlangMap extends OtpErlangObject {
put(key, val);
}
} else {
- map = new HashMap<OtpErlangObject, OtpErlangObject>();
+ map = new OtpMap();
}
}
@@ -350,7 +359,7 @@ public class OtpErlangMap extends OtpErlangObject {
@SuppressWarnings("unchecked")
public Object clone() {
final OtpErlangMap newMap = (OtpErlangMap) super.clone();
- newMap.map = (HashMap<OtpErlangObject, OtpErlangObject>) map.clone();
+ newMap.map = (OtpMap) map.clone();
return newMap;
}
}
diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpInputStream.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpInputStream.java
index 35280f9571..fa0815fbf0 100644
--- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpInputStream.java
+++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpInputStream.java
@@ -1243,6 +1243,9 @@ public class OtpInputStream extends ByteArrayInputStream {
case OtpExternal.funTag:
return new OtpErlangFun(this);
+ case OtpExternal.externalFunTag:
+ return new OtpErlangExternalFun(this);
+
default:
throw new OtpErlangDecodeException("Uknown data type: " + tag);
}
diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpOutputStream.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpOutputStream.java
index 2830a7842e..4faae2a157 100644
--- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpOutputStream.java
+++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpOutputStream.java
@@ -922,8 +922,22 @@ public class OtpOutputStream extends ByteArrayOutputStream {
oos.writeTo(dos);
dos.close(); // note: closes this, too!
} catch (final IllegalArgumentException e) {
- // discard further un-compressed data
- // -> if not called, there may be memory leaks!
+ /*
+ * Discard further un-compressed data (if not called, there may
+ * be memory leaks).
+ *
+ * After calling java.util.zip.Deflater.end(), the deflater
+ * should not be used anymore, not even the close() method of
+ * dos. Calling dos.close() before def.end() is prevented since
+ * an unfinished DeflaterOutputStream will try to deflate its
+ * unprocessed data to the (fixed) byte array which is prevented
+ * by ensureCapacity() and would also unnecessarily process
+ * further data that is discarded anyway.
+ *
+ * Since we are re-using the byte array of this object below, we
+ * must not call close() in e.g. a finally block either (with or
+ * without a call to def.end()).
+ */
def.end();
// could not make the value smaller than originally
// -> reset to starting count, write uncompressed
@@ -942,11 +956,6 @@ public class OtpOutputStream extends ByteArrayOutputStream {
"Intermediate stream failed for Erlang object " + o);
} finally {
fixedSize = Integer.MAX_VALUE;
- try {
- dos.close();
- } catch (final IOException e) {
- // ignore
- }
}
}
}
diff --git a/lib/jinterface/test/nc_SUITE.erl b/lib/jinterface/test/nc_SUITE.erl
index 9679b90a0d..c5f3198c21 100644
--- a/lib/jinterface/test/nc_SUITE.erl
+++ b/lib/jinterface/test/nc_SUITE.erl
@@ -215,6 +215,7 @@ decompress_roundtrip(Config) when is_list(Config) ->
0.0,
math:sqrt(2),
<<1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,31:5>>,
+ "{}",
RandomBin1k,
RandomBin1M,
RandomBin10M,
@@ -244,6 +245,7 @@ compress_roundtrip(Config) when is_list(Config) ->
0.0,
math:sqrt(2),
<<1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,31:5>>,
+ "{}",
RandomBin1k,
RandomBin1M,
RandomBin10M,
diff --git a/lib/kernel/doc/src/code.xml b/lib/kernel/doc/src/code.xml
index 4e3be35079..eb0f4b7a06 100644
--- a/lib/kernel/doc/src/code.xml
+++ b/lib/kernel/doc/src/code.xml
@@ -230,7 +230,7 @@
<c>-code_path_choice Choice</c>. If the flag is set to <c>relaxed</c>,
the code server will instead choose a suitable directory
depending on the actual file structure. If there exists a regular
- application ebin directory,situation it will be chosen. But if it does
+ application ebin directory, it will be chosen. But if it does
not exist, the ebin directory in the archive is chosen if it
exists. If neither of them exists the original directory will be
chosen.</p>
@@ -282,9 +282,9 @@
<p>From the R12B release, functions in this module will generally fail with an
exception if they are passed an incorrect type (for instance, an integer or a tuple
- where an atom was expected). An error tuple will be returned if type of argument
+ where an atom was expected). An error tuple will be returned if the type of the argument
was correct, but there was some other error (for instance, a non-existing directory
- given to <c>set_path/1</c>.</p>
+ was given to <c>set_path/1</c>).</p>
</section>
<datatypes>
diff --git a/lib/kernel/doc/src/file.xml b/lib/kernel/doc/src/file.xml
index 9cd4cfa712..831ef1c22a 100644
--- a/lib/kernel/doc/src/file.xml
+++ b/lib/kernel/doc/src/file.xml
@@ -1194,8 +1194,8 @@
and <c>read_line/1</c> are the only ways to read from a file
opened in raw mode (although they work for normally opened
files, too).</p>
- <p>For files where <c>encoding</c> is set to something else than <c>latin1</c>, one character might be represented by more than one byte on the file. The parameter <c>Number</c> always denotes the number of <em>characters</em> read from the file, why the position in the file might be moved a lot more than this number when reading a Unicode file.</p>
- <p>Also if <c>encoding</c> is set to something else than <c>latin1</c>, the <c>read/3</c> call will fail if the data contains characters larger than 255, why the <seealso marker="stdlib:io">io(3)</seealso> module is to be preferred when reading such a file.</p>
+ <p>For files where <c>encoding</c> is set to something else than <c>latin1</c>, one character might be represented by more than one byte on the file. The parameter <c>Number</c> always denotes the number of <em>characters</em> read from the file, while the position in the file might be moved much more than this number when reading a Unicode file.</p>
+ <p>Also, if <c>encoding</c> is set to something else than <c>latin1</c>, the <c>read/3</c> call will fail if the data contains characters larger than 255, which is why the <seealso marker="stdlib:io">io(3)</seealso> module is to be preferred when reading such a file.</p>
<p>The function returns:</p>
<taglist>
<tag><c>{ok, <anno>Data</anno>}</c></tag>
diff --git a/lib/kernel/doc/src/notes.xml b/lib/kernel/doc/src/notes.xml
index 1e909cb6f2..1049e72ffe 100644
--- a/lib/kernel/doc/src/notes.xml
+++ b/lib/kernel/doc/src/notes.xml
@@ -185,6 +185,22 @@
</section>
+<section><title>Kernel 3.2.0.1</title>
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>The 'raw' socket option could not be used multiple times
+ in one call to any e.g gen_tcp function because only one
+ of the occurrences were used. This bug has been fixed,
+ and also a small bug concerning propagating error codes
+ from within inet:setopts/2.</p>
+ <p>Own Id: OTP-11482 Aux Id: seq12872 </p>
+ </item>
+ </list>
+ </section>
+ </section>
+
+
<section><title>Kernel 3.2</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/kernel/src/code_server.erl b/lib/kernel/src/code_server.erl
index e461c95d19..68dd21b1d7 100644
--- a/lib/kernel/src/code_server.erl
+++ b/lib/kernel/src/code_server.erl
@@ -1428,16 +1428,18 @@ absname_vr([[X, $:]|Name], _, _AbsBase) ->
do_purge(Mod0) ->
Mod = to_atom(Mod0),
case erlang:check_old_code(Mod) of
- false ->
- false;
- true ->
- Res = check_proc_code(erlang:processes(), Mod, true),
- try
- erlang:purge_module(Mod)
- catch
- _:_ -> ignore
- end,
- Res
+ false ->
+ false;
+ true ->
+ true = erlang:copy_literals(Mod, true),
+ Res = check_proc_code(erlang:processes(), Mod, true),
+ true = erlang:copy_literals(Mod, false),
+ try
+ erlang:purge_module(Mod)
+ catch
+ _:_ -> ignore
+ end,
+ Res
end.
%% do_soft_purge(Module)
@@ -1451,10 +1453,13 @@ do_soft_purge(Mod0) ->
false ->
true;
true ->
+ true = erlang:copy_literals(Mod, true),
case check_proc_code(erlang:processes(), Mod, false) of
false ->
+ true = erlang:copy_literals(Mod, false),
false;
true ->
+ true = erlang:copy_literals(Mod, false),
try
erlang:purge_module(Mod)
catch
diff --git a/lib/kernel/src/erts_debug.erl b/lib/kernel/src/erts_debug.erl
index 39308c0043..8e2b5ad214 100644
--- a/lib/kernel/src/erts_debug.erl
+++ b/lib/kernel/src/erts_debug.erl
@@ -34,7 +34,8 @@
-export([breakpoint/2, disassemble/1, display/1, dist_ext_to_term/2,
dump_monitors/1, dump_links/1, flat_size/1,
get_internal_state/1, instructions/0, lock_counters/1,
- map_info/1, same/2, set_internal_state/2]).
+ map_info/1, same/2, set_internal_state/2,
+ size_shared/1, copy_shared/1]).
-spec breakpoint(MFA, Flag) -> non_neg_integer() when
MFA :: {Module :: module(),
@@ -86,6 +87,18 @@ dump_links(_) ->
flat_size(_) ->
erlang:nif_error(undef).
+-spec size_shared(Term) -> non_neg_integer() when
+ Term :: term().
+
+size_shared(_) ->
+ erlang:nif_error(undef).
+
+-spec copy_shared(Term) -> term() when
+ Term :: term().
+
+copy_shared(_) ->
+ erlang:nif_error(undef).
+
-spec get_internal_state(W) -> term() when
W :: reds_left | node_and_dist_references | monitoring_nodes
| next_pid | 'DbTable_words' | check_io_debug
@@ -230,7 +243,7 @@ map_size(Map,Seen0,Sum0) ->
%% is not allowed to leak anywhere. They are only allowed in
%% containers (cons cells and tuples, not maps), in gc and
%% in erts_debug:same/2
- case erts_internal:map_type(Map) of
+ case erts_internal:term_type(Map) of
flatmap ->
Kt = erts_internal:map_to_tuple_keys(Map),
Vs = maps:values(Map),
diff --git a/lib/kernel/src/file_io_server.erl b/lib/kernel/src/file_io_server.erl
index bf8b9e2747..deb7b315b1 100644
--- a/lib/kernel/src/file_io_server.erl
+++ b/lib/kernel/src/file_io_server.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2015. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -206,8 +206,8 @@ io_reply(From, ReplyAs, Reply) ->
file_request({advise,Offset,Length,Advise},
#state{handle=Handle}=State) ->
case ?PRIM_FILE:advise(Handle, Offset, Length, Advise) of
- {error,_}=Reply ->
- {stop,normal,Reply,State};
+ {error,Reason}=Reply ->
+ {stop,Reason,Reply,State};
Reply ->
{reply,Reply,State}
end;
@@ -215,62 +215,91 @@ file_request({allocate, Offset, Length},
#state{handle = Handle} = State) ->
Reply = ?PRIM_FILE:allocate(Handle, Offset, Length),
{reply, Reply, State};
+file_request({pread,At,Sz}, State)
+ when At =:= cur;
+ At =:= {cur,0} ->
+ case get_chars(Sz, latin1, State) of
+ {reply,Reply,NewState}
+ when is_list(Reply);
+ is_binary(Reply) ->
+ {reply,{ok,Reply},NewState};
+ Other ->
+ Other
+ end;
file_request({pread,At,Sz},
- #state{handle=Handle,buf=Buf,read_mode=ReadMode}=State) ->
+ #state{handle=Handle,buf=Buf}=State) ->
case position(Handle, At, Buf) of
- {ok,_Offs} ->
- case ?PRIM_FILE:read(Handle, Sz) of
- {ok,Bin} when ReadMode =:= list ->
- std_reply({ok,binary_to_list(Bin)}, State);
- Reply ->
- std_reply(Reply, State)
- end;
- Reply ->
- std_reply(Reply, State)
+ {error,_} = Reply ->
+ {error,Reply,State};
+ _ ->
+ case get_chars(Sz, latin1, State#state{buf= <<>>}) of
+ {reply,Reply,NewState}
+ when is_list(Reply);
+ is_binary(Reply) ->
+ {reply,{ok,Reply},NewState};
+ Other ->
+ Other
+ end
end;
+file_request({pwrite,At,Data},
+ #state{buf= <<>>}=State)
+ when At =:= cur;
+ At =:= {cur,0} ->
+ put_chars(Data, latin1, State);
file_request({pwrite,At,Data},
#state{handle=Handle,buf=Buf}=State) ->
case position(Handle, At, Buf) of
- {ok,_Offs} ->
- std_reply(?PRIM_FILE:write(Handle, Data), State);
- Reply ->
- std_reply(Reply, State)
+ {error,_} = Reply ->
+ {error,Reply,State};
+ _ ->
+ put_chars(Data, latin1, State)
end;
file_request(datasync,
#state{handle=Handle}=State) ->
case ?PRIM_FILE:datasync(Handle) of
- {error,_}=Reply ->
- {stop,normal,Reply,State};
+ {error,Reason}=Reply ->
+ {stop,Reason,Reply,State};
Reply ->
{reply,Reply,State}
end;
file_request(sync,
#state{handle=Handle}=State) ->
case ?PRIM_FILE:sync(Handle) of
- {error,_}=Reply ->
- {stop,normal,Reply,State};
+ {error,Reason}=Reply ->
+ {stop,Reason,Reply,State};
Reply ->
{reply,Reply,State}
end;
file_request(close,
#state{handle=Handle}=State) ->
- {stop,normal,?PRIM_FILE:close(Handle),State#state{buf= <<>>}};
+ case ?PRIM_FILE:close(Handle) of
+ {error,Reason}=Reply ->
+ {stop,Reason,Reply,State#state{buf= <<>>}};
+ Reply ->
+ {stop,normal,Reply,State#state{buf= <<>>}}
+ end;
file_request({position,At},
#state{handle=Handle,buf=Buf}=State) ->
- std_reply(position(Handle, At, Buf), State);
+ case position(Handle, At, Buf) of
+ {error,_} = Reply ->
+ {error,Reply,State};
+ Reply ->
+ std_reply(Reply, State)
+ end;
file_request(truncate,
#state{handle=Handle}=State) ->
case ?PRIM_FILE:truncate(Handle) of
- {error,_Reason}=Reply ->
- {stop,normal,Reply,State#state{buf= <<>>}};
+ {error,Reason}=Reply ->
+ {stop,Reason,Reply,State#state{buf= <<>>}};
Reply ->
- {reply,Reply,State}
+ std_reply(Reply, State)
end;
file_request(Unknown,
#state{}=State) ->
Reason = {request, Unknown},
{error,{error,Reason},State}.
+%% Standard reply and clear buffer
std_reply({error,_}=Reply, State) ->
{error,Reply,State#state{buf= <<>>}};
std_reply(Reply, State) ->
@@ -286,8 +315,8 @@ io_request({put_chars, Enc, Chars},
io_request({put_chars, Enc, Chars},
#state{handle=Handle,buf=Buf}=State) ->
case position(Handle, cur, Buf) of
- {error,_}=Reply ->
- {stop,normal,Reply,State#state{buf= <<>>}};
+ {error,Reason}=Reply ->
+ {stop,Reason,Reply,State};
_ ->
put_chars(Chars, Enc, State#state{buf= <<>>})
end;
@@ -368,23 +397,27 @@ io_request_loop([Request|Tail],
%% I/O request put_chars
%%
put_chars(Chars, latin1, #state{handle=Handle, unic=latin1}=State) ->
+ NewState = State#state{buf = <<>>},
case ?PRIM_FILE:write(Handle, Chars) of
- {error,_}=Reply ->
- {stop,normal,Reply,State};
+ {error,Reason}=Reply ->
+ {stop,Reason,Reply,NewState};
Reply ->
- {reply,Reply,State}
+ {reply,Reply,NewState}
end;
put_chars(Chars, InEncoding, #state{handle=Handle, unic=OutEncoding}=State) ->
+ NewState = State#state{buf = <<>>},
case unicode:characters_to_binary(Chars,InEncoding,OutEncoding) of
Bin when is_binary(Bin) ->
case ?PRIM_FILE:write(Handle, Bin) of
- {error,_}=Reply ->
- {stop,normal,Reply,State};
+ {error,Reason}=Reply ->
+ {stop,Reason,Reply,NewState};
Reply ->
- {reply,Reply,State}
+ {reply,Reply,NewState}
end;
{error,_,_} ->
- {stop,normal,{error,{no_translation, InEncoding, OutEncoding}},State}
+ {stop,no_translation,
+ {error,{no_translation, InEncoding, OutEncoding}},
+ NewState}
end.
get_line(S, {<<>>, Cont}, OutEnc,
@@ -884,11 +917,14 @@ cbv({utf32,little},_) ->
%% Compensates ?PRIM_FILE:position/2 for the number of bytes
%% we have buffered
-
-position(Handle, cur, Buf) ->
- position(Handle, {cur, 0}, Buf);
-position(Handle, {cur, Offs}, Buf) when is_binary(Buf) ->
- ?PRIM_FILE:position(Handle, {cur, Offs-byte_size(Buf)});
-position(Handle, At, _Buf) ->
- ?PRIM_FILE:position(Handle, At).
-
+position(Handle, At, Buf) ->
+ ?PRIM_FILE:position(
+ Handle,
+ case At of
+ cur ->
+ {cur, -byte_size(Buf)};
+ {cur, Offs} ->
+ {cur, Offs-byte_size(Buf)};
+ _ ->
+ At
+ end).
diff --git a/lib/kernel/src/global.erl b/lib/kernel/src/global.erl
index dcabeb5e49..0c73ead7c5 100644
--- a/lib/kernel/src/global.erl
+++ b/lib/kernel/src/global.erl
@@ -2068,23 +2068,17 @@ get_known() ->
gen_server:call(global_name_server, get_known, infinity).
random_sleep(Times) ->
- case (Times rem 10) of
- 0 -> erase(random_seed);
- _ -> ok
- end,
- case get(random_seed) of
- undefined ->
- _ = random:seed(erlang:phash2([erlang:node()]),
- erlang:monotonic_time(),
- erlang:unique_integer()),
- ok;
- _ -> ok
- end,
+ _ = case Times rem 10 of
+ 0 ->
+ _ = rand:seed(exsplus);
+ _ ->
+ ok
+ end,
%% First time 1/4 seconds, then doubling each time up to 8 seconds max.
Tmax = if Times > 5 -> 8000;
true -> ((1 bsl Times) * 1000) div 8
end,
- T = random:uniform(Tmax),
+ T = rand:uniform(Tmax),
?trace({random_sleep, {me,self()}, {times,Times}, {t,T}, {tmax,Tmax}}),
receive after T -> ok end.
diff --git a/lib/kernel/src/inet.erl b/lib/kernel/src/inet.erl
index 855c6377a3..b573112445 100644
--- a/lib/kernel/src/inet.erl
+++ b/lib/kernel/src/inet.erl
@@ -692,6 +692,7 @@ connect_options(Opts, Family) ->
case con_opt(Opts, BaseOpts, connect_options()) of
{ok, R} ->
{ok, R#connect_opts {
+ opts = lists:reverse(R#connect_opts.opts),
ifaddr = translate_ip(R#connect_opts.ifaddr, Family)
}};
Error -> Error
@@ -762,6 +763,7 @@ listen_options(Opts, Family) ->
case list_opt(Opts, BaseOpts, listen_options()) of
{ok, R} ->
{ok, R#listen_opts {
+ opts = lists:reverse(R#listen_opts.opts),
ifaddr = translate_ip(R#listen_opts.ifaddr, Family)
}};
Error -> Error
@@ -820,6 +822,7 @@ udp_options(Opts, Family) ->
case udp_opt(Opts, #udp_opts { }, udp_options()) of
{ok, R} ->
{ok, R#udp_opts {
+ opts = lists:reverse(R#udp_opts.opts),
ifaddr = translate_ip(R#udp_opts.ifaddr, Family)
}};
Error -> Error
@@ -893,9 +896,12 @@ sctp_options() ->
sctp_options(Opts, Mod) ->
case sctp_opt(Opts, Mod, #sctp_opts{}, sctp_options()) of
{ok,#sctp_opts{ifaddr=undefined}=SO} ->
- {ok,SO#sctp_opts{ifaddr=Mod:translate_ip(?SCTP_DEF_IFADDR)}};
- {ok,_}=OK ->
- OK;
+ {ok,
+ SO#sctp_opts{
+ opts=lists:reverse(SO#sctp_opts.opts),
+ ifaddr=Mod:translate_ip(?SCTP_DEF_IFADDR)}};
+ {ok,SO} ->
+ {ok,SO#sctp_opts{opts=lists:reverse(SO#sctp_opts.opts)}};
Error -> Error
end.
@@ -967,6 +973,8 @@ add_opt(Name, Val, Opts, As) ->
case lists:member(Name, As) of
true ->
case prim_inet:is_sockopt_val(Name, Val) of
+ true when Name =:= raw ->
+ {ok, [{Name,Val} | Opts]};
true ->
Opts1 = lists:keydelete(Name, 1, Opts),
{ok, [{Name,Val} | Opts1]};
diff --git a/lib/kernel/test/file_SUITE.erl b/lib/kernel/test/file_SUITE.erl
index 5263130574..8f5027c91b 100644
--- a/lib/kernel/test/file_SUITE.erl
+++ b/lib/kernel/test/file_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2013. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2015. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -48,7 +48,7 @@
-export([cur_dir_0/1, cur_dir_1/1, make_del_dir/1,
list_dir/1,list_dir_error/1,
untranslatable_names/1, untranslatable_names_error/1,
- pos1/1, pos2/1]).
+ pos1/1, pos2/1, pos3/1]).
-export([close/1, consult1/1, path_consult/1, delete/1]).
-export([ eval1/1, path_eval/1, script1/1, path_script/1,
open1/1,
@@ -80,6 +80,7 @@
-export([interleaved_read_write/1]).
+-export([unicode/1]).
-export([altname/1]).
-export([large_file/1, large_write/1]).
@@ -114,7 +115,7 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- [altname, read_write_file, {group, dirs},
+ [unicode, altname, read_write_file, {group, dirs},
{group, files}, delete, rename, names, {group, errors},
{group, compression}, {group, links}, copy,
delayed_write, read_ahead, segment_read, segment_write,
@@ -136,7 +137,7 @@ groups() ->
[open1, old_modes, new_modes, path_open, close, access,
read_write, pread_write, append, open_errors,
exclusive]},
- {pos, [], [pos1, pos2]},
+ {pos, [], [pos1, pos2, pos3]},
{file_info, [],
[file_info_basic_file, file_info_basic_directory,
file_info_bad, file_info_times, file_write_file_info]},
@@ -1357,6 +1358,27 @@ pos2(Config) when is_list(Config) ->
?line test_server:timetrap_cancel(Dog),
ok.
+pos3(suite) -> [];
+pos3(doc) -> ["When it does not use raw mode, file:position had a bug."];
+pos3(Config) when is_list(Config) ->
+ ?line Dog = test_server:timetrap(test_server:seconds(5)),
+ ?line RootDir = ?config(data_dir, Config),
+ ?line Name = filename:join(RootDir, "realmen.html.gz"),
+
+ ?line {ok, Fd} = ?FILE_MODULE:open(Name, [read, binary]),
+ ?line {ok, _} = ?FILE_MODULE:read(Fd, 5),
+ ?line {error, einval} = ?FILE_MODULE:position(Fd, {bof, -1}),
+
+ %% Here ok had returned =(
+ ?line {error, einval} = ?FILE_MODULE:position(Fd, {cur, -10}),
+ %% That test is actually questionable since file:position/2
+ %% is documented to leave the file position undefined after
+ %% it has returned an error. But on Posix systems the position
+ %% is guaranteed to be unchanged after an error return. On e.g
+ %% Windows there is nothing stated about this in the documentation.
+
+ ?line test_server:timetrap_cancel(Dog),
+ ok.
file_info_basic_file(suite) -> [];
file_info_basic_file(doc) -> [];
@@ -2745,6 +2767,40 @@ compress_async_crash_loop(N, Path, ExpectedData) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+unicode(Config) when is_list(Config) ->
+ Dir = ?config(priv_dir, Config),
+ Name = filename:join(Dir, "data-utf8.txt"),
+ Txt = lists:seq(128, 255),
+ D = unicode:characters_to_binary(Txt, latin1, latin1),
+ {ok,Fd1} =
+ ?FILE_MODULE:open(Name, [write,read,binary,{encoding,unicode}]),
+ ok = ?FILE_MODULE:truncate(Fd1),
+ ok = ?FILE_MODULE:write(Fd1, Txt),
+ {ok,0} = ?FILE_MODULE:position(Fd1, bof),
+ {ok,D} = ?FILE_MODULE:read(Fd1, 129),
+ {ok,0} = ?FILE_MODULE:position(Fd1, bof),
+ {ok,D1} = ?FILE_MODULE:read(Fd1, 64),
+ {ok,Pos} = ?FILE_MODULE:position(Fd1, cur),
+ {ok,D2} = ?FILE_MODULE:pread(Fd1, {cur,0}, 65),
+ D = <<D1/binary, D2/binary>>,
+ {ok,D1} = ?FILE_MODULE:pread(Fd1, bof, 64),
+ {ok,Pos} = ?FILE_MODULE:position(Fd1, Pos),
+ {ok,D2} = ?FILE_MODULE:read(Fd1, 64),
+ ok = ?FILE_MODULE:close(Fd1),
+ %%
+ RawD = unicode:characters_to_binary(Txt, latin1, unicode),
+ {ok,RawD} = ?FILE_MODULE:read_file(Name),
+ %%
+ {ok,Fd2} = ?FILE_MODULE:open(Name, [read,{encoding,unicode}]),
+ {ok,Txt} = ?FILE_MODULE:read(Fd2, 129),
+ {Txt1,Txt2} = lists:split(64, Txt),
+ {ok,Txt2} = ?FILE_MODULE:pread(Fd2, Pos, 65),
+ {ok,0} = ?FILE_MODULE:position(Fd2, bof),
+ {ok,Txt1} = ?FILE_MODULE:read(Fd2, 64),
+ ok = ?FILE_MODULE:close(Fd2).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
altname(doc) ->
"Test the file:altname/1 function";
altname(suite) ->
diff --git a/lib/kernel/test/file_name_SUITE.erl b/lib/kernel/test/file_name_SUITE.erl
index 32006d893e..4c422c9e0a 100644
--- a/lib/kernel/test/file_name_SUITE.erl
+++ b/lib/kernel/test/file_name_SUITE.erl
@@ -159,7 +159,7 @@ normalize(suite) ->
normalize(doc) ->
["Check that filename normalization works"];
normalize(Config) when is_list(Config) ->
- random:seed({1290,431421,830412}),
+ rand:seed(exsplus, {1290,431421,830412}),
try
?line UniMode = file:native_name_encoding() =/= latin1,
if
@@ -845,7 +845,7 @@ conv(L) ->
rand_comp_decomp(Max) ->
- N = random:uniform(Max),
+ N = rand:uniform(Max),
L = [ rand_decomp() || _ <- lists:seq(1,N) ],
LC = [ A || {A,_} <- L],
LD = lists:flatten([B || {_,B} <- L]),
@@ -855,7 +855,7 @@ rand_comp_decomp(Max) ->
rand_decomp() ->
BT = bigtup(),
SZ = tuple_size(BT),
- element(random:uniform(SZ),BT).
+ element(rand:uniform(SZ),BT).
bigtup() ->
{{192,[65,768]},
{200,[69,768]},
diff --git a/lib/kernel/test/gen_tcp_echo_SUITE.erl b/lib/kernel/test/gen_tcp_echo_SUITE.erl
index 6dcb21758b..b5ed16ec34 100644
--- a/lib/kernel/test/gen_tcp_echo_SUITE.erl
+++ b/lib/kernel/test/gen_tcp_echo_SUITE.erl
@@ -442,14 +442,7 @@ random_char(Chars) ->
lists:nth(uniform(length(Chars)), Chars).
uniform(N) ->
- case get(random_seed) of
- undefined ->
- {X, Y, Z} = time(),
- random:seed(X, Y, Z);
- _ ->
- ok
- end,
- random:uniform(N).
+ rand:uniform(N).
put_int32(X, big, List) ->
[ (X bsr 24) band 16#ff,
diff --git a/lib/kernel/test/global_SUITE.erl b/lib/kernel/test/global_SUITE.erl
index 73ee86eba4..c0e24e17fe 100644
--- a/lib/kernel/test/global_SUITE.erl
+++ b/lib/kernel/test/global_SUITE.erl
@@ -2931,7 +2931,7 @@ sync_until(LogFile) ->
timer:sleep(Time).
shuffle(L) ->
- [E || {_, E} <- lists:keysort(1, [{random:uniform(), E} || E <- L])].
+ [E || {_, E} <- lists:keysort(1, [{rand:uniform(), E} || E <- L])].
sync_0(suite) -> [];
sync_0(doc) ->
diff --git a/lib/kernel/test/inet_SUITE.erl b/lib/kernel/test/inet_SUITE.erl
index 5ba06bb032..d64a52fc2c 100644
--- a/lib/kernel/test/inet_SUITE.erl
+++ b/lib/kernel/test/inet_SUITE.erl
@@ -868,7 +868,6 @@ gethostnative_control_2(Seq, Interval, Delay, Cnt, N, Hosts) ->
?line Lookupers =
[spawn_link(
fun () ->
- random:seed(),
lookup_loop(Hosts, Delay, Tag, Parent, Cnt, Hosts)
end)
|| _ <- lists:seq(1, N)],
@@ -929,7 +928,7 @@ lookup_loop([H|Hs], Delay, Tag, Parent, Cnt, Hosts) ->
Parent ! {Tag,Error}
end,
receive
- after random:uniform(Delay) ->
+ after rand:uniform(Delay) ->
lookup_loop(Hs, Delay, Tag, Parent, Cnt-1, Hosts)
end.
diff --git a/lib/kernel/test/inet_res_SUITE.erl b/lib/kernel/test/inet_res_SUITE.erl
index ace4ccb8bd..6e575c2f95 100644
--- a/lib/kernel/test/inet_res_SUITE.erl
+++ b/lib/kernel/test/inet_res_SUITE.erl
@@ -120,7 +120,7 @@ ns_init(ZoneDir, PrivDir, DataDir) ->
{unix,_} ->
PortNum = case {os:type(),os:version()} of
{{unix,solaris},{M,V,_}} when M =< 5, V < 10 ->
- 11895 + random:uniform(100);
+ 11895 + rand:uniform(100);
_ ->
{ok,S} = gen_udp:open(0, [{reuseaddr,true}]),
{ok,PNum} = inet:port(S),
diff --git a/lib/kernel/test/inet_sockopt_SUITE.erl b/lib/kernel/test/inet_sockopt_SUITE.erl
index 1262f36fae..cb522c8abe 100644
--- a/lib/kernel/test/inet_sockopt_SUITE.erl
+++ b/lib/kernel/test/inet_sockopt_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2015. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -52,6 +52,7 @@
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2,
simple/1, loop_all/1, simple_raw/1, simple_raw_getbin/1,
+ multiple_raw/1, multiple_raw_getbin/1,
doc_examples_raw/1,doc_examples_raw_getbin/1,
large_raw/1,large_raw_getbin/1,combined/1,combined_getbin/1,
ipv6_v6only_udp/1, ipv6_v6only_tcp/1, ipv6_v6only_sctp/1,
@@ -65,6 +66,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[simple, loop_all, simple_raw, simple_raw_getbin,
+ multiple_raw, multiple_raw_getbin,
doc_examples_raw, doc_examples_raw_getbin, large_raw,
large_raw_getbin, combined, combined_getbin,
ipv6_v6only_udp, ipv6_v6only_tcp, ipv6_v6only_sctp,
@@ -185,6 +187,84 @@ nintbin2int(<<Int:16/native>>) -> Int;
nintbin2int(<<Int:8/native>>) -> Int;
nintbin2int(<<>>) -> 0.
+
+
+multiple_raw(suite) -> [];
+multiple_raw(doc) -> "Test setopt/getopt of multiple raw options.";
+multiple_raw(Config) when is_list(Config) ->
+ do_multiple_raw(Config,false).
+multiple_raw_getbin(suite) -> [];
+multiple_raw_getbin(doc) -> "Test setopt/getopt of multiple raw options, "
+ "with binaries in getopt.";
+multiple_raw_getbin(Config) when is_list(Config) ->
+ do_multiple_raw(Config,true).
+
+do_multiple_raw(Config, Binary) ->
+ Port = start_helper(Config),
+ SolSocket = ask_helper(Port, ?C_GET_SOL_SOCKET),
+ SoKeepalive = ask_helper(Port, ?C_GET_SO_KEEPALIVE),
+ SoKeepaliveTrue = {raw,SolSocket,SoKeepalive,<<1:32/native>>},
+ SoKeepaliveFalse = {raw,SolSocket,SoKeepalive,<<0:32/native>>},
+ SoReuseaddr = ask_helper(Port, ?C_GET_SO_REUSEADDR),
+ SoReuseaddrTrue = {raw,SolSocket,SoReuseaddr,<<1:32/native>>},
+ SoReuseaddrFalse = {raw,SolSocket,SoReuseaddr,<<0:32/native>>},
+ {S1,S2} =
+ create_socketpair(
+ [SoReuseaddrFalse,SoKeepaliveTrue],
+ [SoKeepaliveFalse,SoReuseaddrTrue]),
+ {ok,[{reuseaddr,false},{keepalive,true}]} =
+ inet:getopts(S1, [reuseaddr,keepalive]),
+ {ok,
+ [{raw,SolSocket,SoReuseaddr,S1R1},
+ {raw,SolSocket,SoKeepalive,S1K1}]} =
+ inet:getopts(
+ S1,
+ [{raw,SolSocket,SoReuseaddr,binarify(4, Binary)},
+ {raw,SolSocket,SoKeepalive,binarify(4, Binary)}]),
+ true = nintbin2int(S1R1) =:= 0,
+ true = nintbin2int(S1K1) =/= 0,
+ {ok,[{keepalive,false},{reuseaddr,true}]} =
+ inet:getopts(S2, [keepalive,reuseaddr]),
+ {ok,
+ [{raw,SolSocket,SoKeepalive,S2K1},
+ {raw,SolSocket,SoReuseaddr,S2R1}]} =
+ inet:getopts(
+ S2,
+ [{raw,SolSocket,SoKeepalive,binarify(4, Binary)},
+ {raw,SolSocket,SoReuseaddr,binarify(4, Binary)}]),
+ true = nintbin2int(S2K1) =:= 0,
+ true = nintbin2int(S2R1) =/= 0,
+ %%
+ ok = inet:setopts(
+ S1, [SoReuseaddrTrue,SoKeepaliveFalse]),
+ ok = inet:setopts(
+ S2, [SoKeepaliveTrue,SoReuseaddrFalse]),
+ {ok,
+ [{raw,SolSocket,SoReuseaddr,S1R2},
+ {raw,SolSocket,SoKeepalive,S1K2}]} =
+ inet:getopts(
+ S1,
+ [{raw,SolSocket,SoReuseaddr,binarify(4, Binary)},
+ {raw,SolSocket,SoKeepalive,binarify(4, Binary)}]),
+ true = nintbin2int(S1R2) =/= 0,
+ true = nintbin2int(S1K2) =:= 0,
+ {ok,
+ [{raw,SolSocket,SoKeepalive,S2K2},
+ {raw,SolSocket,SoReuseaddr,S2R2}]} =
+ inet:getopts(
+ S2,
+ [{raw,SolSocket,SoKeepalive,binarify(4, Binary)},
+ {raw,SolSocket,SoReuseaddr,binarify(4, Binary)}]),
+ true = nintbin2int(S2K2) =/= 0,
+ true = nintbin2int(S2R2) =:= 0,
+ %%
+ gen_tcp:close(S1),
+ gen_tcp:close(S2),
+ stop_helper(Port),
+ ok.
+
+
+
doc_examples_raw(suite) -> [];
doc_examples_raw(doc) -> "Test that the example code from the documentation "
"works";
diff --git a/lib/kernel/test/zlib_SUITE.erl b/lib/kernel/test/zlib_SUITE.erl
index 6aaa024a82..77fdabe73c 100644
--- a/lib/kernel/test/zlib_SUITE.erl
+++ b/lib/kernel/test/zlib_SUITE.erl
@@ -912,7 +912,7 @@ smp(Config) ->
FnAList = lists:map(fun(F) -> {F,?MODULE:F({get_arg,Config})}
end, Funcs),
- Pids = [spawn_link(?MODULE, worker, [random:uniform(9999),
+ Pids = [spawn_link(?MODULE, worker, [rand:uniform(9999),
list_to_tuple(FnAList),
self()])
|| _ <- lists:seq(1,NumOfProcs)],
@@ -925,7 +925,7 @@ smp(Config) ->
worker(Seed, FnATpl, Parent) ->
io:format("smp worker ~p, seed=~p~n",[self(),Seed]),
- random:seed(Seed,Seed,Seed),
+ rand:seed(exsplus, {Seed,Seed,Seed}),
worker_loop(100, FnATpl),
Parent ! self().
@@ -933,7 +933,7 @@ worker_loop(0, _FnATpl) ->
large_deflate_do(), % the time consuming one as finale
ok;
worker_loop(N, FnATpl) ->
- {F,A} = element(random:uniform(size(FnATpl)),FnATpl),
+ {F,A} = element(rand:uniform(tuple_size(FnATpl)), FnATpl),
?MODULE:F(A),
worker_loop(N-1, FnATpl).
diff --git a/lib/mnesia/src/mnesia_lib.erl b/lib/mnesia/src/mnesia_lib.erl
index 77c7a7638d..4e761d2bed 100644
--- a/lib/mnesia/src/mnesia_lib.erl
+++ b/lib/mnesia/src/mnesia_lib.erl
@@ -921,20 +921,7 @@ random_time(Retries, _Counter0) ->
UpperLimit = 500,
Dup = Retries * Retries,
MaxIntv = trunc(UpperLimit * (1-(50/((Dup)+50)))),
-
- case get(random_seed) of
- undefined ->
- _ = random:seed(erlang:unique_integer(),
- erlang:monotonic_time(),
- erlang:unique_integer()),
- Time = Dup + random:uniform(MaxIntv),
- %% dbg_out("---random_test rs ~w max ~w val ~w---~n", [Retries, MaxIntv, Time]),
- Time;
- _ ->
- Time = Dup + random:uniform(MaxIntv),
- %% dbg_out("---random_test rs ~w max ~w val ~w---~n", [Retries, MaxIntv, Time]),
- Time
- end.
+ Dup + rand:uniform(MaxIntv).
report_system_event(Event0) ->
Event = {mnesia_system_event, Event0},
diff --git a/lib/mnesia/test/mnesia_consistency_test.erl b/lib/mnesia/test/mnesia_consistency_test.erl
index 087aef86c9..279e7bc1ec 100644
--- a/lib/mnesia/test/mnesia_consistency_test.erl
+++ b/lib/mnesia/test/mnesia_consistency_test.erl
@@ -696,7 +696,7 @@ consistency_after_restore(ReplicaType, Op, Config) ->
?verify_mnesia(Nodes, []).
change_tab(Father, Tab, Test) ->
- Key = random:uniform(20),
+ Key = rand:uniform(20),
Update = fun() ->
case mnesia:read({Tab, Key}) of
[{Tab, Key, 1}] ->
diff --git a/lib/observer/doc/src/crashdump_ug.xml b/lib/observer/doc/src/crashdump_ug.xml
index 3cd97f2f18..4bb3628ab5 100644
--- a/lib/observer/doc/src/crashdump_ug.xml
+++ b/lib/observer/doc/src/crashdump_ug.xml
@@ -377,7 +377,6 @@
<p>The <em>Memory</em> panel shows memory and allocator
information. From the left hand menu you can select:</p>
- <p>
<list>
<item><em>Memory</em> <seealso
@@ -394,7 +393,6 @@
marker="erts:crash_dump#allocated_areas">More...</seealso></item>
</list>
- </p>
</section>
<section>
diff --git a/lib/observer/doc/src/notes.xml b/lib/observer/doc/src/notes.xml
index 5243f50e34..f0c87d865e 100644
--- a/lib/observer/doc/src/notes.xml
+++ b/lib/observer/doc/src/notes.xml
@@ -273,13 +273,12 @@
<section><title>Improvements and New Features</title>
<list>
<item>
- <p>
<list> <item> The new Memory field from a crash dump is
now presented by crashdump viewer, both in the process
overview and in the process detail page. </item> <item> A
summary of blocks- and carriers sizes is added to the
allocator information page in the crashdump viewer.
- </item> </list></p>
+ </item> </list>
<p>
Own Id: OTP-10604 Aux Id: kunagi-336 [247] </p>
</item>
@@ -408,7 +407,6 @@
<item>
<p>
The following bugs in <c>ttb</c> have been corrected:</p>
- <p>
<list> <item><c>ttb:tracer/2</c> would earlier crash when
trying to set up tracing for a diskless node to wrap
files, i.e. when option
@@ -421,7 +419,7 @@
<c>{file,{local,Filename}}</c></item> <item>A deadlock
would sometimes occur due to an information printout from
the <c>ttb_control</c> process when <c>ttb</c> was
- stopped.</item> </list></p>
+ stopped.</item> </list>
<p>
Own Id: OTP-9431</p>
</item>
@@ -449,7 +447,6 @@
<item>
<p>
The following new features are added to <c>ttb</c>:</p>
- <p>
<list> <item>A one-command trace setup is added,
<c>ttb:start_trace/4</c>.</item> <item>The following new
options are added to <c>ttb:tracer/2</c>: <list>
@@ -485,7 +482,7 @@
<c>disable_sort</c> is added to <c>ttb:format/2</c>. When
this option is used, trace messages from different logs
are not merged according to timestamps, but just appended
- one log after the other. </item> </list></p>
+ one log after the other. </item> </list>
<p>
Own Id: OTP-9403</p>
</item>
@@ -493,7 +490,6 @@
<p>
The following non backwards compatible changes are done
in <c>ttb</c>:</p>
- <p>
<list> <item> When setting up trace with ttb, the
'timestamp' trace flag will now always be set. </item>
<item> The 'fetch' option to ttb:stop/1 is removed since
@@ -509,7 +505,7 @@
trace file, this is now changed so the handler state is
passed not only from one trace message to the next in the
same file, but also from one file to the next. </item>
- </list></p>
+ </list>
<p>
*** POTENTIAL INCOMPATIBILITY ***</p>
<p>
diff --git a/lib/observer/doc/src/observer_ug.xml b/lib/observer/doc/src/observer_ug.xml
index 8388cb6736..ff30d70913 100644
--- a/lib/observer/doc/src/observer_ug.xml
+++ b/lib/observer/doc/src/observer_ug.xml
@@ -105,7 +105,7 @@
<note>
<p><em>Reds</em> can be presented as accumulated values or as values since last update.</p>
</note>
- <p><c>Process info</c> open a detailed information window on the selected process.
+ <p><c>Process info</c> open a detailed information window on the selected process.</p>
<taglist>
<tag>Process Information</tag>
<item>Shows the process information.</item>
@@ -127,7 +127,6 @@
<c>rb</c> server will be stopped on the observed node when exiting or changing observed node.
</p>
</note>
- </p>
<p><c>Trace Processes</c> will add the selected process identifiers to the <c>Trace Overview</c> view and the
node the processes reside on will be added as well.
<c>Trace Named Processes</c> will add the registered name of processes. This can be useful
diff --git a/lib/observer/doc/src/ttb.xml b/lib/observer/doc/src/ttb.xml
index 0b064b51b8..0a50a20716 100644
--- a/lib/observer/doc/src/ttb.xml
+++ b/lib/observer/doc/src/ttb.xml
@@ -25,8 +25,7 @@
</legalnotice>
<title>ttb</title>
- <prepared>Siri hansen</prepared>
- <prepared>Bartlomiej Puzon</prepared>
+ <prepared>Siri hansen, Bartlomiej Puzon</prepared>
<responsible></responsible>
<docno>1</docno>
<approved></approved>
@@ -60,17 +59,16 @@
<p>This function is a shortcut allowing to start a trace with one command. Each
tuple in <c>Patterns</c> is converted to list which is in turn passed to
<c>ttb:tpl</c>.
- The call:<code type="none">
+ The call:</p><code type="none">
ttb:start_trace([Node, OtherNode],
[{mod, foo, []}, {mod, bar, 2}],
{all, call},
[{file, File}, {handler,{fun myhandler/4, S}}])</code>
- is equivalent to <code type="none">
+ <p>is equivalent to</p> <code type="none">
ttb:start_trace([Node, OtherNode], [{file, File}, {handler,{fun myhandler/4, S}}]),
ttb:tpl(mod, foo, []),
ttb:tpl(mod, bar, 2, []),
ttb:p(all, call)</code>
- </p>
</desc>
</func>
<func>
@@ -193,7 +191,7 @@ ttb:p(all, call)</code>
(i.e. on diskless nodes), a custom module to handle autostart
information storage and retrieval can be provided by specifying
<c>ttb_autostart_module</c> environment variable for the <c>runtime_tools</c>
- application. The module has to respond to the following API:
+ application. The module has to respond to the following API:</p>
<taglist>
<tag><c>write_config(Data) -> ok</c></tag>
<item>Store the provided data for further retrieval. It is
@@ -207,7 +205,6 @@ ttb:p(all, call)</code>
must return <c>{error, Error}</c>.
</item>
</taglist>
- </p>
<p>The <c>resume</c> option implies the default <c>FetchTimeout</c>, which is
10 seconds</p>
</desc>
@@ -272,17 +269,19 @@ ttb:p(all, call)</code>
<item>Clear trace pattern on global function calls</item>
</taglist>
<p>With <c>tp</c> and <c>tpl</c> one of match specification shortcuts
- may be used (example: <c>ttb:tp(foo_module, caller)</c>). The shortcuts are:
+ may be used (example: <c>ttb:tp(foo_module, caller)</c>). The shortcuts are:</p>
<taglist>
+ <tag/>
<item><c>return</c> - for <c>[{'_',[],[{return_trace}]}]</c>
(report the return value)</item>
+ <tag/>
<item><c>caller</c> - for <c>[{'_',[],[{message,{caller}}]}]</c>
(report the calling function)</item>
+ <tag/>
<item><c>{codestr, Str}</c> - for <c>dbg:fun2ms/1</c> arguments
passed as strings (example: <c>"fun(_) -> return_trace() end"</c>)
</item>
</taglist>
- </p>
</desc>
</func>
<func>
diff --git a/lib/observer/doc/src/ttb_ug.xml b/lib/observer/doc/src/ttb_ug.xml
index ba8c997133..e2a28d67d0 100644
--- a/lib/observer/doc/src/ttb_ug.xml
+++ b/lib/observer/doc/src/ttb_ug.xml
@@ -320,7 +320,7 @@ do_print(Out,{trace_ts,P,return_from,{M,F,A},R,Ts},N) ->
</code>
</section>
<section>
- <label>Overload protection</label>
+ <title>Overload protection</title>
<p>When tracing live systems, special care needs to be always taken
not to overload a node with too heavy tracing. <c>ttb</c> provides
the <c>overload</c> option to help to address the problem.</p>
@@ -747,7 +747,7 @@ f3() ->
of the <c>ttb</c> for setting trace flags on processes and trace
patterns for call trace, i.e. the functions <c>p</c>, <c>tp</c>,
<c>tpl</c>, <c>ctp</c>, <c>ctpl</c> and <c>ctpg</c>. There are only
- two things added by <c>ttb</c> for these functions:
+ two things added by <c>ttb</c> for these functions:</p>
<list type="bulleted">
<item>all calls are stored in the history buffer and can be
recalled and stored in a configuration file. This makes it
@@ -756,9 +756,8 @@ f3() ->
typing when using <c>ttb</c> from the erlang shell;</item>
<item>shortcuts are provided for the most common match
specifications (in order not to force the user to use
- <c>dbg:fun2ms</c> continually</item>).
+ <c>dbg:fun2ms</c> continually).</item>
</list>
- </p>
<p>Use <c>list_history/0</c> to see the content of the history
buffer, and <c>run_history/1</c> to re-execute one of the entries.
</p>
diff --git a/lib/observer/src/observer_html_lib.erl b/lib/observer/src/observer_html_lib.erl
index 9d8c2d998c..f646f8ed3e 100644
--- a/lib/observer/src/observer_html_lib.erl
+++ b/lib/observer/src/observer_html_lib.erl
@@ -387,7 +387,9 @@ remove_lgt(Deep) ->
remove_lgt_1([$<,$<|Rest]) ->
[$>,$>|BinStr] = lists:reverse(Rest),
- replace_lgt(lists:reverse(BinStr)).
+ replace_lgt(lists:reverse(BinStr));
+remove_lgt_1(TruncBin) ->
+ TruncBin.
replace_lgt([$<|R]) ->
["&lt;"|replace_lgt(R)];
diff --git a/lib/orber/doc/src/notes.xml b/lib/orber/doc/src/notes.xml
index 3f7d4121fd..7b5d0f96ca 100644
--- a/lib/orber/doc/src/notes.xml
+++ b/lib/orber/doc/src/notes.xml
@@ -169,11 +169,9 @@
<section><title>Known Bugs and Problems</title>
<list>
<item>
- <p>
<p>
- </p></p>
- <p>
- Own Id: OTP-10675 Aux Id: seq12154 </p>
+ Own Id: OTP-10675 Aux Id: seq12154
+ </p>
</item>
</list>
</section>
diff --git a/lib/percept/test/egd_SUITE.erl b/lib/percept/test/egd_SUITE.erl
index 41e8999e17..5a0a9af14d 100644
--- a/lib/percept/test/egd_SUITE.erl
+++ b/lib/percept/test/egd_SUITE.erl
@@ -40,7 +40,7 @@
-define(default_timeout, ?t:minutes(1)).
init_per_suite(Config) when is_list(Config) ->
- random:seed(now()),
+ rand:seed(exsplus),
Config.
end_per_suite(Config) when is_list(Config) ->
@@ -348,4 +348,4 @@ get_points(0, Out) ->
get_points(N, Out) ->
get_points(N - 1, [get_point() | Out]).
-random(N) -> trunc(random:uniform(trunc(N + 1)) - 1).
+random(N) -> trunc(rand:uniform(trunc(N + 1)) - 1).
diff --git a/lib/public_key/asn1/PKIX1Explicit88.asn1 b/lib/public_key/asn1/PKIX1Explicit88.asn1
index 91758d7269..81fec8283e 100644
--- a/lib/public_key/asn1/PKIX1Explicit88.asn1
+++ b/lib/public_key/asn1/PKIX1Explicit88.asn1
@@ -86,22 +86,22 @@ id-at-initials AttributeType ::= { id-at 43 }
id-at-generationQualifier AttributeType ::= { id-at 44 }
X520name ::= CHOICE {
- teletexString TeletexString (SIZE (1..ub-name)),
- printableString PrintableString (SIZE (1..ub-name)),
- universalString UniversalString (SIZE (1..ub-name)),
- utf8String UTF8String (SIZE (1..ub-name)),
- bmpString BMPString (SIZE (1..ub-name)) }
+ teletexString TeletexString (SIZE (1..ub-name-teletex)),
+ printableString PrintableString (SIZE (1..ub-name-printable)),
+ universalString UniversalString (SIZE (1..ub-name-universal)),
+ utf8String UTF8String (SIZE (1..ub-name-utf8)),
+ bmpString BMPString (SIZE (1..ub-name-universal)) }
-- Naming attributes of type X520CommonName
id-at-commonName AttributeType ::= { id-at 3 }
X520CommonName ::= CHOICE {
- teletexString TeletexString (SIZE (1..ub-common-name)),
- printableString PrintableString (SIZE (1..ub-common-name)),
- universalString UniversalString (SIZE (1..ub-common-name)),
- utf8String UTF8String (SIZE (1..ub-common-name)),
- bmpString BMPString (SIZE (1..ub-common-name)) }
+ teletexString TeletexString (SIZE (1..ub-common-name-teletex)),
+ printableString PrintableString (SIZE (1..ub-common-name-printable)),
+ universalString UniversalString (SIZE (1..ub-common-name-universal)),
+ utf8String UTF8String (SIZE (1..ub-common-name-utf8)),
+ bmpString BMPString (SIZE (1..ub-common-name-universal)) }
-- Naming attributes of type X520LocalityName
@@ -110,9 +110,9 @@ id-at-localityName AttributeType ::= { id-at 7 }
X520LocalityName ::= CHOICE {
teletexString TeletexString (SIZE (1..ub-locality-name)),
printableString PrintableString (SIZE (1..ub-locality-name)),
- universalString UniversalString (SIZE (1..ub-locality-name)),
- utf8String UTF8String (SIZE (1..ub-locality-name)),
- bmpString BMPString (SIZE (1..ub-locality-name)) }
+ universalString UniversalString (SIZE (1..ub-locality-name-universal)),
+ utf8String UTF8String (SIZE (1..ub-locality-name-utf8)),
+ bmpString BMPString (SIZE (1..ub-locality-name-universal)) }
-- Naming attributes of type X520StateOrProvinceName
@@ -121,9 +121,9 @@ id-at-stateOrProvinceName AttributeType ::= { id-at 8 }
X520StateOrProvinceName ::= CHOICE {
teletexString TeletexString (SIZE (1..ub-state-name)),
printableString PrintableString (SIZE (1..ub-state-name)),
- universalString UniversalString (SIZE (1..ub-state-name)),
- utf8String UTF8String (SIZE (1..ub-state-name)),
- bmpString BMPString (SIZE(1..ub-state-name)) }
+ universalString UniversalString (SIZE (1..ub-state-name-universal)),
+ utf8String UTF8String (SIZE (1..ub-state-name-utf8)),
+ bmpString BMPString (SIZE(1..ub-state-name-universal)) }
-- Naming attributes of type X520OrganizationName
@@ -131,15 +131,15 @@ id-at-organizationName AttributeType ::= { id-at 10 }
X520OrganizationName ::= CHOICE {
teletexString TeletexString
- (SIZE (1..ub-organization-name)),
+ (SIZE (1..ub-organization-name-teletex)),
printableString PrintableString
- (SIZE (1..ub-organization-name)),
+ (SIZE (1..ub-organization-name-printable)),
universalString UniversalString
- (SIZE (1..ub-organization-name)),
+ (SIZE (1..ub-organization-name-universal)),
utf8String UTF8String
- (SIZE (1..ub-organization-name)),
+ (SIZE (1..ub-organization-name-utf8)),
bmpString BMPString
- (SIZE (1..ub-organization-name)) }
+ (SIZE (1..ub-organization-name-universal)) }
-- Naming attributes of type X520OrganizationalUnitName
@@ -147,26 +147,26 @@ id-at-organizationalUnitName AttributeType ::= { id-at 11 }
X520OrganizationalUnitName ::= CHOICE {
teletexString TeletexString
- (SIZE (1..ub-organizational-unit-name)),
+ (SIZE (1..ub-organizational-unit-name-teletex)),
printableString PrintableString
- (SIZE (1..ub-organizational-unit-name)),
+ (SIZE (1..ub-organizational-unit-name-printable)),
universalString UniversalString
- (SIZE (1..ub-organizational-unit-name)),
+ (SIZE (1..ub-organizational-unit-name-universal)),
utf8String UTF8String
- (SIZE (1..ub-organizational-unit-name)),
+ (SIZE (1..ub-organizational-unit-name-utf8)),
bmpString BMPString
- (SIZE (1..ub-organizational-unit-name)) }
+ (SIZE (1..ub-organizational-unit-name-universal)) }
-- Naming attributes of type X520Title
id-at-title AttributeType ::= { id-at 12 }
X520Title ::= CHOICE {
- teletexString TeletexString (SIZE (1..ub-title)),
- printableString PrintableString (SIZE (1..ub-title)),
- universalString UniversalString (SIZE (1..ub-title)),
- utf8String UTF8String (SIZE (1..ub-title)),
- bmpString BMPString (SIZE (1..ub-title)) }
+ teletexString TeletexString (SIZE (1..ub-title-teletex)),
+ printableString PrintableString (SIZE (1..ub-title-printable)),
+ universalString UniversalString (SIZE (1..ub-title-universal)),
+ utf8String UTF8String (SIZE (1..ub-title-utf8)),
+ bmpString BMPString (SIZE (1..ub-title-universal)) }
-- Naming attributes of type X520dnQualifier
@@ -193,9 +193,9 @@ id-at-pseudonym AttributeType ::= { id-at 65 }
X520Pseudonym ::= CHOICE {
teletexString TeletexString (SIZE (1..ub-pseudonym)),
printableString PrintableString (SIZE (1..ub-pseudonym)),
- universalString UniversalString (SIZE (1..ub-pseudonym)),
- utf8String UTF8String (SIZE (1..ub-pseudonym)),
- bmpString BMPString (SIZE (1..ub-pseudonym)) }
+ universalString UniversalString (SIZE (1..ub-pseudonym-universal)),
+ utf8String UTF8String (SIZE (1..ub-pseudonym-utf8)),
+ bmpString BMPString (SIZE (1..ub-pseudonym-universal)) }
-- Naming attributes of type DomainComponent (from RFC 2247)
@@ -363,7 +363,7 @@ PrivateDomainName ::= CHOICE {
printable PrintableString (SIZE (1..ub-domain-name-length)) }
OrganizationName ::= PrintableString
- (SIZE (1..ub-organization-name-length))
+ (SIZE (1..ub-organization-name-printable))
-- see also teletex-organization-name
NumericUserIdentifier ::= NumericString
@@ -386,7 +386,7 @@ OrganizationalUnitNames ::= SEQUENCE SIZE (1..ub-organizational-units)
-- see also teletex-organizational-unit-names
OrganizationalUnitName ::= PrintableString (SIZE
- (1..ub-organizational-unit-name-length))
+ (1..ub-organizational-unit-name-printable))
-- Built-in Domain-defined Attributes
@@ -415,16 +415,16 @@ ExtensionAttribute ::= SEQUENCE {
common-name INTEGER ::= 1
-CommonName ::= PrintableString (SIZE (1..ub-common-name-length))
+CommonName ::= PrintableString (SIZE (1..ub-common-name-printable))
teletex-common-name INTEGER ::= 2
-TeletexCommonName ::= TeletexString (SIZE (1..ub-common-name-length))
+TeletexCommonName ::= TeletexString (SIZE (1..ub-common-name-teletex))
teletex-organization-name INTEGER ::= 3
TeletexOrganizationName ::=
- TeletexString (SIZE (1..ub-organization-name-length))
+ TeletexString (SIZE (1..ub-organization-name-teletex))
teletex-personal-name INTEGER ::= 4
@@ -445,7 +445,7 @@ TeletexOrganizationalUnitNames ::= SEQUENCE SIZE
(1..ub-organizational-units) OF TeletexOrganizationalUnitName
TeletexOrganizationalUnitName ::= TeletexString
- (SIZE (1..ub-organizational-unit-name-length))
+ (SIZE (1..ub-organizational-unit-name-teletex))
pds-name INTEGER ::= 7
@@ -570,16 +570,39 @@ TeletexDomainDefinedAttribute ::= SEQUENCE {
-- Upper Bounds
ub-name INTEGER ::= 32768
+ub-name-teletex INTEGER ::= 65536
+ub-name-printable INTEGER ::= 65536
+ub-name-universal INTEGER ::= 131072
+ub-name-utf8 INTEGER ::= 131072
ub-common-name INTEGER ::= 64
+ub-common-name-teletex INTEGER::= 128
+ub-common-name-printable INTEGER ::= 128
+ub-common-name-universal INTEGER ::= 256
+ub-common-name-utf8 INTEGER ::= 256
ub-locality-name INTEGER ::= 128
+ub-locality-name-utf8 INTEGER ::= 256
+ub-locality-name-universal INTEGER ::= 256
ub-state-name INTEGER ::= 128
+ub-state-name-universal INTEGER ::= 256
+ub-state-name-utf8 INTEGER ::= 256
ub-organization-name INTEGER ::= 64
+ub-organization-name-printable INTEGER ::= 128
+ub-organization-name-teletex INTEGER ::= 128
+ub-organization-name-universal INTEGER ::= 256
+ub-organization-name-utf8 INTEGER ::= 256
ub-organizational-unit-name INTEGER ::= 64
+ub-organizational-unit-name-printable INTEGER ::= 128
+ub-organizational-unit-name-teletex INTEGER ::= 128
+ub-organizational-unit-name-universal INTEGER ::= 256
+ub-organizational-unit-name-utf8 INTEGER ::= 256
ub-title INTEGER ::= 64
+ub-title-teletex INTEGER ::= 128
+ub-title-printable INTEGER ::= 128
+ub-title-universal INTEGER ::= 256
+ub-title-utf8 INTEGER ::= 256
ub-serial-number INTEGER ::= 64
ub-match INTEGER ::= 128
ub-emailaddress-length INTEGER ::= 255
-ub-common-name-length INTEGER ::= 64
ub-country-name-alpha-length INTEGER ::= 2
ub-country-name-numeric-length INTEGER ::= 3
ub-domain-defined-attributes INTEGER ::= 4
@@ -594,14 +617,14 @@ ub-given-name-length INTEGER ::= 16
ub-initials-length INTEGER ::= 5
ub-integer-options INTEGER ::= 256
ub-numeric-user-id-length INTEGER ::= 32
-ub-organization-name-length INTEGER ::= 64
-ub-organizational-unit-name-length INTEGER ::= 32
ub-organizational-units INTEGER ::= 4
ub-pds-name-length INTEGER ::= 16
ub-pds-parameter-length INTEGER ::= 30
ub-pds-physical-address-lines INTEGER ::= 6
ub-postal-code-length INTEGER ::= 16
ub-pseudonym INTEGER ::= 128
+ub-pseudonym-utf8 INTEGER ::= 256
+ub-pseudonym-universal INTEGER ::= 256
ub-surname-length INTEGER ::= 40
ub-terminal-id-length INTEGER ::= 24
ub-unformatted-address-length INTEGER ::= 180
diff --git a/lib/public_key/vsn.mk b/lib/public_key/vsn.mk
index f762473a58..d5ffe6ca35 100644
--- a/lib/public_key/vsn.mk
+++ b/lib/public_key/vsn.mk
@@ -1 +1 @@
-PUBLIC_KEY_VSN = 1.0.1
+PUBLIC_KEY_VSN = 1.1
diff --git a/lib/reltool/src/reltool_fgraph_win.erl b/lib/reltool/src/reltool_fgraph_win.erl
index 6b58cae187..deab502bfe 100644
--- a/lib/reltool/src/reltool_fgraph_win.erl
+++ b/lib/reltool/src/reltool_fgraph_win.erl
@@ -220,8 +220,8 @@ graph_add_node_unsure(Key, State, G = #graph{ vs = Vs }) ->
graph_add_node(Key, Color, G = #graph{ vs = Vs}) ->
Q = 20.0, % repulsive force
M = 0.5, % mass
- P = {float(450 + random:uniform(100)),
- float(450 + random:uniform(100))},
+ P = {float(450 + rand:uniform(100)),
+ float(450 + rand:uniform(100))},
G#graph{ vs = reltool_fgraph:add(Key,
#fg_v{ p = P, m = M, q = Q, color = Color},
Vs)}.
diff --git a/lib/sasl/doc/src/alarm_handler.xml b/lib/sasl/doc/src/alarm_handler.xml
index b98f22d2a1..68076ba28d 100644
--- a/lib/sasl/doc/src/alarm_handler.xml
+++ b/lib/sasl/doc/src/alarm_handler.xml
@@ -37,94 +37,92 @@
<module>alarm_handler</module>
<modulesummary>An Alarm Handling Process</modulesummary>
<description>
- <p>The alarm handler process is a <c>gen_event</c> event manager
- process which receives alarms in the system. This process is not
- intended to be a complete alarm handler. It defines a
- place to which alarms can be sent. One simple event handler is
- installed in the alarm handler at start-up, but users are
- encouraged to write and install their own handlers.
- </p>
+ <p>The alarm handler process is a
+ <seealso marker="stdlib:gen_event"><c>gen_event</c></seealso>
+ event manager process that receives alarms in the system.
+ This process is not intended to be a complete alarm handler.
+ It defines a place to which alarms can be sent. One simple event
+ handler is installed in the alarm handler at startup, but users
+ are encouraged to write and install their own handlers.</p>
<p>The simple event handler sends all alarms as info reports to
- the error logger, and saves all of them in a list which can be
- passed to a user defined event handler, which may be installed at
- a later stage. The list can grow large if many alarms are
- generated. So it is a good reason to install a better user defined
- handler.
- </p>
- <p>There are functions to set and clear alarms. The format of
- alarms are defined by the user. For example, an event handler
- for SNMP could be defined, together with an alarm MIB.
- </p>
- <p>The alarm handler is part of the SASL application.
- </p>
+ the error logger, and saves all in a list. This list can be
+ passed to a user-defined event handler, which can be installed
+ later. The list can grow large if many alarms are generated.
+ This is a good reason to install a better user-defined
+ handler.</p>
+ <p>Functions are provided to set and clear alarms. The alarm
+ format is defined by the user. For example, an event handler
+ for SNMP can be defined, together with an alarm Management
+ Information Base (MIB).</p>
+ <p>The alarm handler is part of the <c>SASL</c> application.</p>
<p>When writing new event handlers for the alarm handler, the
- following events must be handled:
- </p>
+ following events must be handled:</p>
<taglist>
<tag><c>{set_alarm, {AlarmId, AlarmDescr}}</c></tag>
<item>
<p>This event is generated by
- <c>alarm_handler:set_alarm({AlarmId, AlarmDecsr})</c>.
- </p>
+ <c>alarm_handler:set_alarm({AlarmId, AlarmDecsr})</c>.</p>
</item>
<tag><c>{clear_alarm, AlarmId}</c></tag>
<item>
<p>This event is
- generated by <c>alarm_handler:clear_alarm(AlarmId)</c>.
- </p>
+ generated by <c>alarm_handler:clear_alarm(AlarmId)</c>.</p>
</item>
</taglist>
<p>The default simple handler is called <c>alarm_handler</c> and
- it may be exchanged by calling <c>gen_event:swap_handler/3</c>
- as <c>gen_event:swap_handler(alarm_handler, {alarm_handler, swap}, {NewHandler, Args})</c>. <c>NewHandler:init({Args, {alarm_handler, Alarms}})</c> is called. Refer to gen_event(3)
- for further details.
- </p>
+ it can be exchanged by calling
+ <seealso marker="stdlib:gen_event#swap_handler/3"><c>gen_event:swap_handler/3</c></seealso>
+ as <c>gen_event:swap_handler(alarm_handler, {alarm_handler, swap},
+ {NewHandler, Args})</c>. <c>NewHandler:init({Args, {alarm_handler,
+ Alarms}})</c> is called. For more details, see
+ <seealso marker="stdlib:gen_event"><c>gen_event(3)</c></seealso>
+ in <c>STDLIB</c>.</p>
</description>
+
<funcs>
<func>
<name>clear_alarm(AlarmId) -> void()</name>
- <fsummary>Clear the specified alarms</fsummary>
+ <fsummary>Clears the specified alarms.</fsummary>
<type>
<v>AlarmId = term()</v>
</type>
<desc>
- <p>Sends the <c>clear_alarm</c> event to all event handlers.</p>
+ <p>Sends event <c>clear_alarm</c> to all event handlers.</p>
<p>When receiving this event, the default simple handler
- clears the latest received alarm with id <c>AlarmId</c>.
- </p>
+ clears the latest received alarm with id <c>AlarmId</c>.</p>
</desc>
</func>
+
<func>
<name>get_alarms() -> [alarm()]</name>
- <fsummary>Get all active alarms</fsummary>
+ <fsummary>Gets all active alarms.</fsummary>
<desc>
<p>Returns a list of all active alarms. This function can only
- be used when the simple handler is installed.
- </p>
+ be used when the simple handler is installed.</p>
</desc>
</func>
+
<func>
<name>set_alarm(alarm())</name>
- <fsummary>Set an alarm with an id</fsummary>
+ <fsummary>Sets an alarm with an id.</fsummary>
<type>
<v>alarm() = {AlarmId, AlarmDescription}</v>
<v>AlarmId = term()</v>
<v>AlarmDescription = term()</v>
</type>
<desc>
- <p>Sends the <c>set_alarm</c> event to all event handlers.</p>
+ <p>Sends event <c>set_alarm</c> to all event handlers.</p>
<p>When receiving this event, the default simple handler
- stores the alarm. The <c>AlarmId</c> identifies the alarm
- and is used when the alarm is cleared.
- </p>
+ stores the alarm. <c>AlarmId</c> identifies the alarm
+ and is used when the alarm is cleared.</p>
</desc>
</func>
</funcs>
<section>
<title>See Also</title>
- <p>error_logger(3), gen_event(3)
- </p>
+ <p><seealso marker="kernel:error_logger"><c>error_logger(3)</c></seealso>,
+ <seealso marker="stdlib:gen_event"><c>gen_event(3)</c></seealso></p>
</section>
</erlref>
diff --git a/lib/sasl/doc/src/appup.xml b/lib/sasl/doc/src/appup.xml
index 72333960ec..b54d2adb19 100644
--- a/lib/sasl/doc/src/appup.xml
+++ b/lib/sasl/doc/src/appup.xml
@@ -29,78 +29,85 @@
<rev></rev>
</header>
<file>appup</file>
- <filesummary>Application upgrade file.</filesummary>
+ <filesummary>Application upgrade file</filesummary>
<description>
<p>The <em>application upgrade file</em> defines how an application
is upgraded or downgraded in a running system.</p>
- <p>This file is used by the functions in <c>systools</c> when
- generating a release upgrade file <c>relup</c>.</p>
+ <p>This file is used by the functions in
+ <seealso marker="systools"><c>systools</c></seealso>
+ when generating a release upgrade file <c>relup</c>.</p>
</description>
<section>
- <title>FILE SYNTAX</title>
- <p>The application upgrade file should be called
- <c>Application.appup</c> where <c>Application</c> is the name of
- the application. The file should be located in the <c>ebin</c>
+ <title>File Syntax</title>
+ <p>The application upgrade file is to be called
+ <c>Application.appup</c>, where <c>Application</c> is the
+ application name. The file is to be located in the <c>ebin</c>
directory for the application.</p>
<p>The <c>.appup</c> file contains one single Erlang term, which
defines the instructions used to upgrade or downgrade
- the application. The file has the following syntax:</p>
+ the application. The file has the following syntax:</p>
<code type="none">
{Vsn,
[{UpFromVsn, Instructions}, ...],
- [{DownToVsn, Instructions}, ...]}.
- </code>
- <list type="bulleted">
- <item>
- <p><c>Vsn = string()</c> is the current version of
- the application.</p>
- </item>
- <item>
- <p><c>UpFromVsn = string() | binary()</c> is an earlier
- version of the application to upgrade from. If it is a
- string, it will be interpreted as a specific version
- number. If it is a binary, it will be interpreted as a
- regular expression which can match multiple version
- numbers.</p>
- </item>
- <item>
- <p><c>DownToVsn = string() | binary()</c> is an earlier
- version of the application to downgrade to. If it is a
- string, it will be interpreted as a specific version
- number. If it is a binary, it will be interpreted as a
- regular expression which can match multiple version
- numbers.</p>
- </item>
- <item>
- <p><c>Instructions</c> is a list of <em>release upgrade instructions</em>, see below. It is recommended to use
+ [{DownToVsn, Instructions}, ...]}.</code>
+ <taglist>
+ <tag><c>Vsn = string()</c></tag>
+ <item><p>Current application version.</p></item>
+ <tag><c>UpFromVsn = string() | binary()</c></tag>
+ <item><p>An earlier
+ application version to upgrade from. If it is a
+ string, it is interpreted as a specific version
+ number. If it is a binary, it is interpreted as a
+ regular expression that can match multiple version
+ numbers.</p></item>
+ <tag><c>DownToVsn = string() | binary()</c></tag>
+ <item><p>An earlier
+ application version to downgrade to. If it is a
+ string, it is interpreted as a specific version
+ number. If it is a binary, it is interpreted as a
+ regular expression that can match multiple version
+ numbers.</p></item>
+ <tag><c>Instructions</c></tag>
+ <item><p>A list of <em>release upgrade instructions</em>, see
+ <seealso marker="#Release Upgrade Instructions">Release
+ Upgrade Instructions</seealso>. It is recommended to use
high-level instructions only. These are automatically
translated to low-level instructions by <c>systools</c> when
- creating the <c>relup</c> file.</p>
- </item>
- </list>
- <p>In order to avoid duplication of upgrade instructions it is
- allowed to use regular expressions to specify the <c>UpFromVsn</c>
- and <c>DownToVsn</c>. To be considered a regular expression, the
- version identifier must be specified as a binary, e.g.</p>
- <code type="none">&lt;&lt;"2\\.1\\.[0-9]+">></code>
- <p>will match all versions <c>2.1.x</c>, where x is any number.</p>
- <p>Note that the regular expression must match the complete
- version string, so the above example will work for for
- e.g. <c>2.1.1</c>, but not for <c>2.1.1.1</c></p>
+ creating the <c>relup</c> file.</p></item>
+ </taglist>
+ <p>To avoid duplication of upgrade instructions, it is
+ allowed to use regular expressions to specify <c>UpFromVsn</c>
+ and <c>DownToVsn</c>. To be considered a regular expression, the
+ version identifier must be specified as a binary. For example,
+ the following match all versions <c>2.1.x</c>, where <c>x</c> is
+ any number:</p>
+ <code type="none">
+&lt;&lt;"2\\.1\\.[0-9]+">></code>
+ <p>Notice that the regular expression must match the complete
+ version string, so this example works for, for example,
+ <c>2.1.1</c>, but not for <c>2.1.1.1</c>.</p>
</section>
<section>
- <title>RELEASE UPGRADE INSTRUCTIONS</title>
+ <marker id="Release Upgrade Instructions"></marker>
+ <title>Release Upgrade Instructions</title>
<p>Release upgrade instructions are interpreted by the release
handler when an upgrade or downgrade is made. For more
- information about release handling, refer to <em>OTP Design Principles</em>.</p>
- <p>A process is said to <em>use</em> a module <c>Mod</c>, if
+ information about release handling, see
+ <seealso marker="doc/design_principles:release_handling">OTP
+ Design Principles</seealso> in <em>System Documentation</em>.</p>
+ <p>A process is said to <em>use</em> a module <c>Mod</c> if
<c>Mod</c> is listed in the <c>Modules</c> part of the child
- specification used to start the process, see <c>supervisor(3)</c>.
- In the case of gen_event, an event manager process is said to use
- <c>Mod</c> if <c>Mod</c> is an installed event handler.</p>
- <p><em>High-level instructions</em></p>
+ specification used to start the process, see
+ <seealso marker="stdlib:supervisor"><c>supervisor(3)</c></seealso>.
+ In the case of
+ <seealso marker="stdlib:gen_event"><c>gen_event</c></seealso>,
+ an event manager process is said to use <c>Mod</c> if <c>Mod</c>
+ is an installed event handler.</p>
+
+ <section>
+ <title>High-Level Instructions</title>
<pre>
{update, Mod}
{update, Mod, supervisor}
@@ -116,52 +123,68 @@
Change = soft | {advanced,Extra}
Extra = term()
PrePurge = PostPurge = soft_purge | brutal_purge
- DepMods = [Mod]
- </pre>
- <p>Synchronized code replacement of processes using the module
- <c>Mod</c>. All those processes are suspended using
- <c>sys:suspend</c>, the new version of the module is loaded and
- then the processes are resumed using <c>sys:resume</c>.</p>
- <p><c>Change</c> defaults to <c>soft</c> and defines the type of
- code change. If it is set to <c>{advanced,Extra}</c>, processes
- implemented using gen_server, gen_fsm or gen_event will transform
- their internal state by calling the callback function
- <c>code_change</c>. Special processes will call the callback
+ DepMods = [Mod]</pre>
+ <p>Synchronized code replacement of processes using module
+ <c>Mod</c>.</p>
+ <p>All those processes are suspended using
+ <seealso marker="stdlib:sys#suspend/1"><c>sys:suspend</c></seealso>,
+ the new module version is loaded, and
+ then the processes are resumed using
+ <seealso marker="stdlib:sys#resume/1"><c>sys:resume</c></seealso>.</p>
+ <taglist>
+ <tag><c>Change</c></tag>
+ <item><p>Defaults to <c>soft</c> and defines the type of
+ code change. If it is set to <c>{advanced,Extra}</c>, implemented
+ processes using
+ <seealso marker="stdlib:gen_server"><c>gen_server</c></seealso>,
+ <seealso marker="stdlib:gen_fsm"><c>gen_fsm</c></seealso>, or
+ <seealso marker="stdlib:gen_event"><c>gen_event</c></seealso>
+ transform their internal state by calling the callback function
+ <c>code_change</c>. Special processes call the callback
function <c>system_code_change/4</c>. In both cases, the term
- <c>Extra</c> is passed as an argument to the callback function.</p>
- <p><c>PrePurge</c> defaults to <c>brutal_purge</c> and controls
- what action to take with processes that are executing old code
- before loading the new version of the module. If the value
+ <c>Extra</c> is passed as an argument to the callback
+ function.</p></item>
+ <tag><c>PrePurge</c></tag>
+ <item><p>Defaults to <c>brutal_purge</c>. It controls
+ what action to take with processes executing old code
+ before loading the new module version. If the value
is <c>brutal_purge</c>, the processes are killed. If the value is
- <c>soft_purge</c>, <c>release_handler:install_release/1</c>
- returns <c>{error,{old_processes,Mod}}</c>.</p>
- <p><c>PostPurge</c> defaults to <c>brutal_purge</c> and controls
+ <c>soft_purge</c>,
+ <seealso marker="release_handler#install_release/1"><c>release_handler:install_release/1</c></seealso>
+ returns <c>{error,{old_processes,Mod}}</c>.</p></item>
+ <tag><c>PostPurge</c></tag>
+ <item><p>Defaults to <c>brutal_purge</c>. It controls
what action to take with processes that are executing old code
- when the new version of the module has been loaded. If the value
+ when the new module version has been loaded. If the value
is <c>brutal_purge</c>, the code is purged when the release is
made permanent and the processes are killed. If the value is
- <c>soft_purge</c>, the release handler will purge the old code
- when no remaining processes execute the code.</p>
- <p><c>DepMods</c> defaults to [] and defines which other modules
- <c>Mod</c> is dependent on. In <c>relup</c>, instructions for
- suspending processes using <c>Mod</c> will come before
+ <c>soft_purge</c>, the release handler purges the old code
+ when no remaining processes execute the code.</p></item>
+ <tag><c>DepMods</c></tag>
+ <item><p>Defaults to <c>[]</c> and defines other modules that
+ <c>Mod</c> is dependent on. In the <c>relup</c> file, instructions
+ for suspending processes using <c>Mod</c> come before
instructions for suspending processes using modules in
- <c>DepMods</c> when upgrading, and vice versa when downgrading.
+ <c>DepMods</c> when upgrading, and conversely when downgrading.
In case of circular dependencies, the order of the instructions in
- the <c>appup</c> script is kept.</p>
- <p><c>Timeout</c> defines the timeout when suspending processes.
- If no value or <c>default</c> is given, the default value for
- <c>sys:suspend</c> is used.</p>
- <p><c>ModType</c> defaults to <c>dynamic</c> and specifies if
- the code is "dynamic", that is if a process using the module does
- spontaneously switch to new code, or if it is "static".
- When doing an advanced update and upgrading, the new version of a
+ the <c>appup</c> file is kept.</p></item>
+ <tag><c>Timeout</c></tag>
+ <item><p>Defines the time-out when suspending processes.
+ If no value or <c>default</c> is specified, the default value for
+ <seealso marker="stdlib:sys#suspend/1"><c>sys:suspend</c></seealso>
+ is used.</p></item>
+ <tag><c>ModType</c></tag>
+ <item><p>Defaults to <c>dynamic</c>. It specifies if
+ the code is "dynamic", that is, if a process using the module
+ spontaneously switches to new code, or if it is "static".
+ When doing an advanced update and upgrade, the new version of a
dynamic module is loaded before the process is asked to change
code. When downgrading, the process is asked to change code before
loading the new version. For static modules, the new version is
loaded before the process is asked to change code, both in
the case of upgrading and downgrading. Callback modules are
- dynamic.</p>
+ dynamic.</p></item>
+ </taglist>
<p><c>update</c> with argument <c>supervisor</c> is used when
changing the start specification of a supervisor.</p>
<pre>
@@ -170,239 +193,229 @@
{load_module, Mod, PrePurge, PostPurge, DepMods}
Mod = atom()
PrePurge = PostPurge = soft_purge | brutal_purge
- DepMods = [Mod]
- </pre>
+ DepMods = [Mod]</pre>
<p>Simple code replacement of the module <c>Mod</c>.</p>
- <p>See <c>update</c> above for a description of <c>PrePurge</c> and
- <c>PostPurge</c>.</p>
- <p><c>DepMods</c> defaults to [] and defines which other modules
- <c>Mod</c> is dependent on. In <c>relup</c>, instructions for
- loading these modules will come before the instruction for loading
- <c>Mod</c> when upgrading, and vice versa when downgrading.</p>
+ <p>For a description of <c>PrePurge</c> and <c>PostPurge</c>,
+ see <c>update</c> above.</p>
+ <p><c>DepMods</c> defaults to <c>[]</c> and defines which other modules
+ <c>Mod</c> is dependent on. In the <c>relup</c> file, instructions for
+ loading these modules come before the instruction for loading
+ <c>Mod</c> when upgrading, and conversely when downgrading.</p>
<pre>
{add_module, Mod}
{add_module, Mod, DepMods}
Mod = atom()
- DepMods = [Mod]
- </pre>
+ DepMods = [Mod]</pre>
<p>Loads a new module <c>Mod</c>.</p>
- <p><c>DepMods</c> defaults to [] and defines which other modules
- <c>Mod</c> is dependent on. In <c>relup</c>, instructions
- related to these modules will come before the instruction for
- loading <c>Mod</c> when upgrading, and vice versa when
+ <p><c>DepMods</c> defaults to <c>[]</c> and defines which other modules
+ <c>Mod</c> is dependent on. In the <c>relup</c> file, instructions
+ related to these modules come before the instruction for
+ loading <c>Mod</c> when upgrading, and conversely when
downgrading.</p>
<pre>
{delete_module, Mod}
{delete_module, Mod, DepMods}
- Mod = atom()
- </pre>
+ Mod = atom()</pre>
<p>Deletes a module <c>Mod</c> using the low-level instructions
<c>remove</c> and <c>purge</c>.</p>
- <p><c>DepMods</c> defaults to [] and defines which other modules
- <c>Mod</c> is dependent on. In <c>relup</c>, instructions
- related to these modules will come before the instruction for
- removing <c>Mod</c> when upgrading, and vice versa when
+ <p><c>DepMods</c> defaults to <c>[]</c> and defines which other modules
+ <c>Mod</c> is dependent on. In the <c>relup</c> file, instructions
+ related to these modules come before the instruction for
+ removing <c>Mod</c> when upgrading, and conversely when
downgrading.</p>
<pre>
{add_application, Application}
{add_application, Application, Type}
Application = atom()
- Type = permanent | transient | temporary | load | none
- </pre>
+ Type = permanent | transient | temporary | load | none</pre>
<p>Adding an application means that the modules defined by
the <c>modules</c> key in the <c>.app</c> file are loaded using
<c>add_module</c>.</p>
<p><c>Type</c> defaults to <c>permanent</c> and specifies the start type
of the application. If <c>Type = permanent | transient | temporary</c>,
- the application will be loaded and started in the corresponding way,
- see <c>application(3)</c>. If <c>Type = load</c>, the application will
- only be loaded. If <c>Type = none</c>, the application will be neither
- loaded nor started, although the code for its modules will be loaded.</p>
+ the application is loaded and started in the corresponding way, see
+ <seealso marker="kernel:application"><c>application(3)</c></seealso>.
+ If <c>Type = load</c>, the application is only loaded.
+ If <c>Type = none</c>, the application is not loaded and not
+ started, although the code for its modules is loaded.</p>
<pre>
{remove_application, Application}
- Application = atom()
- </pre>
+ Application = atom()</pre>
<p>Removing an application means that the application is stopped,
- the modules are unloaded using <c>delete_module</c> and then
+ the modules are unloaded using <c>delete_module</c>, and then
the application specification is unloaded from the application
controller.</p>
<pre>
{restart_application, Application}
- Application = atom()
- </pre>
+ Application = atom()</pre>
<p>Restarting an application means that the application is
- stopped and then started again similar to using the instructions
+ stopped and then started again, similar to using the instructions
<c>remove_application</c> and <c>add_application</c> in sequence.</p>
- <p><em>Low-level instructions</em></p>
+ </section>
+
+ <section>
+ <title>Low-Level Instructions</title>
<pre>
{load_object_code, {App, Vsn, [Mod]}}
App = Mod = atom()
- Vsn = string()
- </pre>
- <p>Reads each <c>Mod</c> from the directory <c>App-Vsn/ebin</c> as
- a binary. It does not load the modules. The instruction should be
- placed first in the script in order to read all new code from file
- to make the suspend-load-resume cycle less time consuming. After
- this instruction has been executed, the code server with the new
- version of <c>App</c>.</p>
+ Vsn = string()</pre>
+ <p>Reads each <c>Mod</c> from directory <c>App-Vsn/ebin</c> as
+ a binary. It does not load the modules. The instruction is to be
+ placed first in the script to read all new code from the file
+ to make the suspend-load-resume cycle less time-consuming.</p>
<pre>
-point_of_no_return
- </pre>
+point_of_no_return</pre>
<p>If a crash occurs after this instruction, the system cannot
- recover and is restarted from the old version of the release.
- The instruction must only occur once in a script. It should be
+ recover and is restarted from the old release version.
+ The instruction must only occur once in a script. It is to be
placed after all <c>load_object_code</c> instructions.</p>
<pre>
{load, {Mod, PrePurge, PostPurge}}
Mod = atom()
- PrePurge = PostPurge = soft_purge | brutal_purge
- </pre>
+ PrePurge = PostPurge = soft_purge | brutal_purge</pre>
<p>Before this instruction occurs, <c>Mod</c> must have been loaded
using <c>load_object_code</c>. This instruction loads the module.
- <c>PrePurge</c> is ignored. See the high-level instruction
- <c>update</c> for a description of <c>PostPurge</c>.</p>
+ <c>PrePurge</c> is ignored. For a description of <c>PostPurge</c>,
+ see the high-level instruction <c>update</c> earlier.</p>
<pre>
{remove, {Mod, PrePurge, PostPurge}}
Mod = atom()
- PrePurge = PostPurge = soft_purge | brutal_purge
- </pre>
+ PrePurge = PostPurge = soft_purge | brutal_purge</pre>
<p>Makes the current version of <c>Mod</c> old.
- <c>PrePurge</c> is ignored. See the high-level instruction
- <c>update</c> for a description of <c>PostPurge</c>.</p>
+ <c>PrePurge</c> is ignored. For a description of <c>PostPurge</c>,
+ see the high-level instruction <c>update</c> earlier.</p>
<pre>
{purge, [Mod]}
- Mod = atom()
- </pre>
- <p>Purges each module <c>Mod</c>, that is removes the old code.
- Note that any process executing purged code is killed.</p>
+ Mod = atom()</pre>
+ <p>Purges each module <c>Mod</c>, that is, removes the old code.
+ Notice that any process executing purged code is killed.</p>
<pre>
{suspend, [Mod | {Mod, Timeout}]}
Mod = atom()
- Timeout = int()>0 | default | infinity
- </pre>
+ Timeout = int()>0 | default | infinity</pre>
<p>Tries to suspend all processes using a module <c>Mod</c>. If a
- process does not respond, it is ignored. This may cause
+ process does not respond, it is ignored. This can cause
the process to die, either because it crashes when it
spontaneously switches to new code, or as a result of a purge
operation. If no <c>Timeout</c> is specified or <c>default</c> is
- given, the default value for <c>sys:suspend</c> is used.</p>
+ specified, the default value for
+ <seealso marker="stdlib:sys#suspend/1"><c>sys:suspend</c></seealso>
+ is used.</p>
<pre>
{resume, [Mod]}
- Mod = atom()
- </pre>
+ Mod = atom()</pre>
<p>Resumes all suspended processes using a module <c>Mod</c>.</p>
<pre>
{code_change, [{Mod, Extra}]}
{code_change, Mode, [{Mod, Extra}]}
Mod = atom()
Mode = up | down
- Extra = term()
- </pre>
+ Extra = term()</pre>
<p><c>Mode</c> defaults to <c>up</c> and specifies if it is an
- upgrade or downgrade.</p>
- <p>This instruction sends a <c>code_change</c> system message to
- all processes using a module <c>Mod</c> by calling the function
- <c>sys:change_code</c>, passing the term <c>Extra</c> as argument.</p>
+ upgrade or downgrade. This instruction sends a <c>code_change</c>
+ system message to all processes using a module <c>Mod</c> by
+ calling function
+ <seealso marker="stdlib:sys#change_code/4"><c>sys:change_code</c></seealso>,
+ passing term <c>Extra</c> as argument.</p>
<pre>
{stop, [Mod]}
- Mod = atom()
- </pre>
+ Mod = atom()</pre>
<p>Stops all processes using a module <c>Mod</c> by calling
- <c>supervisor:terminate_child/2</c>. The instruction is useful
+ <seealso marker="stdlib:supervisor#terminate_child/2"><c>supervisor:terminate_child/2</c></seealso>.
+ This instruction is useful
when the simplest way to change code is to stop and restart the
- processes which run the code.</p>
+ processes that run the code.</p>
<pre>
{start, [Mod]}
- Mod = atom()
- </pre>
+ Mod = atom()</pre>
<p>Starts all stopped processes using a module <c>Mod</c> by calling
- <c>supervisor:restart_child/2</c>.</p>
+ <seealso marker="stdlib:supervisor#restart_child/2"><c>supervisor:restart_child/2</c></seealso>.</p>
<pre>
{sync_nodes, Id, [Node]}
{sync_nodes, Id, {M, F, A}}
Id = term()
Node = node()
M = F = atom()
- A = [term()]
- </pre>
+ A = [term()]</pre>
<p><c>apply(M, F, A)</c> must return a list of nodes.</p>
- <p>The instruction synchronizes the release installation with other
- nodes. Each <c>Node</c> must evaluate this command, with the same
+ <p>This instruction synchronizes the release installation with other
+ nodes. Each <c>Node</c> must evaluate this command with the same
<c>Id</c>. The local node waits for all other nodes to evaluate
- the instruction before execution continues. In case a node goes
+ the instruction before execution continues. If a node goes
down, it is considered to be an unrecoverable error, and
the local node is restarted from the old release. There is no
- timeout for this instruction, which means that it may hang
+ time-out for this instruction, which means that it can hang
forever.</p>
<pre>
{apply, {M, F, A}}
M = F = atom()
- A = [term()]
- </pre>
- <p>Evaluates <c>apply(M, F, A)</c>. If the instruction appears
- before the <c>point_of_no_return</c> instruction, a failure is
- caught. <c>release_handler:install_release/1</c> then returns
- <c>{error,{'EXIT',Reason}}</c>, unless <c>{error,Error}</c> is
- thrown or returned. Then it returns <c>{error,Error}</c>.</p>
- <p>If the instruction appears after the <c>point_of_no_return</c>
- instruction, and the function call fails, the system is
- restarted.</p>
+ A = [term()]</pre>
+ <p>Evaluates <c>apply(M, F, A)</c>.</p>
+ <p>If the instruction appears before instruction
+ <c>point_of_no_return</c>, a failure is caught.
+ <seealso marker="release_handler#install_release/1"><c>release_handler:install_release/1</c></seealso>
+ then returns <c>{error,{'EXIT',Reason}}</c>, unless <c>{error,Error}</c>
+ is thrown or returned. Then it returns <c>{error,Error}</c>.</p>
+ <p>If the instruction appears after instruction
+ <c>point_of_no_return</c> and the function call fails, the
+ system is restarted.</p>
<pre>
-restart_new_emulator
- </pre>
- <p>This instruction is used when erts, kernel, stdlib or sasl is
+restart_new_emulator</pre>
+ <p>This instruction is used when the application <c>ERTS</c>,
+ <c>Kernel</c>, <c>STDLIB</c>, or <c>SASL</c> is
upgraded. It shuts down the current emulator and starts a new
one. All processes are terminated gracefully, and the new
- version of erts, kernel, stdlib and sasl are used when the
- emulator restarts. Only one <c>restart_new_emulator</c>
- instruction is allowed in the relup, and it shall be placed
- first. <seealso marker="systools#make_relup/3">systools:make_relup/3,4</seealso>
- will ensure this when the relup is generated. The rest of the
- relup script is executed after the restart as a part of the boot
- script.</p>
- <p>An info report will be written when the upgrade is
- completed. To programatically find out if the upgrade is
- complete,
+ version of <c>ERTS</c>, <c>Kernel</c>, <c>STDLIB</c>, and
+ <c>SASL</c> are used when the emulator restarts.
+ Only one <c>restart_new_emulator</c> instruction is allowed
+ in the <c>relup</c> file, and it must be placed first.
+ <seealso marker="systools#make_relup/3"><c>systools:make_relup/3,4</c></seealso>
+ ensures this when the <c>relup</c> file is generated. The rest of the
+ instructions in the <c>relup</c> file is executed after the
+ restart as a part of the boot script.</p>
+ <p>An info report is written when the upgrade is completed.
+ To programmatically determine if the upgrade is complete,
call <seealso marker="release_handler#which_releases/0">
- release_handler:which_releases/0,1</seealso> and check if the
+ <c>release_handler:which_releases/0,1</c></seealso> and check if the
expected release has status <c>current</c>.</p>
<p>The new release must still be made permanent after the upgrade
- is completed. Otherwise, the old emulator is started in case of
+ is completed, otherwise the old emulator is started if there is
an emulator restart.</p>
<warning>
- <p>As stated above, the <c>restart_new_emulator</c>
- instruction causes the emulator to be restarted with new
- versions of <c>erts</c>, <c>kernel</c>, <c>stdlib</c> and
- <c>sasl</c>. All other applications, however, will at startup
- be running their old versions in this new emulator. In most
- cases this is no problem, but every now and then there will be
- incompatible changes to the core applications which may cause
- trouble in this setting. Such incompatible changes (when
- functions are removed) are normally preceded by a deprecation
- over two major releases. To make sure your application is not
- crashed by an incompatible change, always remove any call to
- deprecated functions as soon as possible.</p>
+ <p>As stated earlier, instruction <c>restart_new_emulator</c>
+ causes the emulator to be restarted with new versions of
+ <c>ERTS</c>, <c>Kernel</c>, <c>STDLIB</c>, and <c>SASL</c>.
+ However, all other applications do at startup run their old
+ versions in this new emulator. This is usually no problem,
+ but every now and then incompatible changes occur to the
+ core applications, which can cause
+ trouble in this setting. Such incompatible changes (when
+ functions are removed) are normally preceded by a deprecation
+ over two major releases. To ensure that your application is not
+ crashed by an incompatible change, always remove any call to
+ deprecated functions as soon as possible.</p>
</warning>
<pre>
-restart_emulator
- </pre>
+restart_emulator</pre>
<p>This instruction is similar to <c>restart_new_emulator</c>,
- except it shall be placed at the end of the relup script. It is
- not related to an upgrade of the emulator or the core
+ except it must be placed at the end of the <c>relup</c> file.
+ It is not related to an upgrade of the emulator or the core
applications, but can be used by any application when a complete
- reboot of the system is reqiured. When generating the
- relup, <seealso marker="systools#make_relup/3">systools:make_relup/3,4</seealso>
+ reboot of the system is required.</p>
+ <p>When generating the <c>relup</c> file,
+ <seealso marker="systools#make_relup/3"><c>systools:make_relup/3,4</c></seealso>
ensures that there is only one <c>restart_emulator</c>
- instruction and that it is the last instruction of the
- relup.</p>
+ instruction and that it is the last instruction in the
+ <c>relup</c> file.</p>
+ </section>
</section>
<section>
- <title>SEE ALSO</title>
- <p><seealso marker="relup">relup(4)</seealso>,
- <seealso marker="release_handler">release_handler(3)</seealso>,
- supervisor(3),
- <seealso marker="systools">systools(3)</seealso></p>
+ <title>See Also</title>
+ <p><seealso marker="release_handler"><c>release_handler(3)</c></seealso>,
+ <seealso marker="relup"><c>relup(4)</c></seealso>,
+ <seealso marker="stdlib:supervisor"><c>supervisor(3)</c></seealso>,
+ <seealso marker="systools"><c>systools(3)</c></seealso></p>
</section>
</fileref>
diff --git a/lib/sasl/doc/src/book.xml b/lib/sasl/doc/src/book.xml
index 2bb5339d94..624c32a66f 100644
--- a/lib/sasl/doc/src/book.xml
+++ b/lib/sasl/doc/src/book.xml
@@ -22,7 +22,7 @@
</legalnotice>
- <title>System Application Support Libraries (SASL)</title>
+ <title>System Architecture Support Libraries (SASL)</title>
<prepared>OTP Team</prepared>
<docno></docno>
<date>1999-04-22</date>
@@ -31,7 +31,7 @@
</header>
<insidecover>
</insidecover>
- <pagetext>System Application Support Libraries (SASL)</pagetext>
+ <pagetext>System Architecture Support Libraries (SASL)</pagetext>
<preamble>
<contents level="2"></contents>
</preamble>
diff --git a/lib/sasl/doc/src/error_logging.xml b/lib/sasl/doc/src/error_logging.xml
index 7c45b1970e..46b12f3872 100644
--- a/lib/sasl/doc/src/error_logging.xml
+++ b/lib/sasl/doc/src/error_logging.xml
@@ -31,89 +31,93 @@
<date>1999-04-13</date>
<rev>B</rev>
<file>error_logging.xml</file>
- </header>
- <p>The SASL application introduces three types of reports:</p>
+ </header>
+ <p>The <c>SASL</c> application introduces three types of reports:</p>
<list type="bulleted">
- <item>supervisor report</item>
- <item>progress report</item>
- <item>crash report.</item>
+ <item>Supervisor report</item>
+ <item>Progress report</item>
+ <item>Crash report</item>
</list>
- <p>When the SASL application is started, it adds a handler that
- formats and writes these reports, as specified in the
- configuration parameters for sasl, i.e the environment variables
- in the SASL application specification, which is found in the
- <c>.app</c> file of SASL. See
- <seealso marker="sasl_app">sasl(Application)</seealso>, and app(File)
- in the Kernel Reference Manual
- for the details.</p>
+ <p>When the <c>SASL</c> application is started, it adds a handler that
+ formats and writes these reports, as specified in the configuration
+ parameters for <c>SASL</c>, that is, the environment variables
+ in the <c>SASL</c> application specification, which is found in the
+ <c>.app</c> file of <c>SASL</c>. For details, see the
+ <seealso marker="sasl_app"><c>sasl(6)</c></seealso> application in the
+ Reference Manual and the <seealso marker="kernel:app"><c>app(4)</c></seealso>
+ file in the <c>Kernel</c> Reference Manual.</p>
<section>
<title>Supervisor Report</title>
- <p>A supervisor report is issued when a supervised child terminates in
- an unexpected way. A supervisor report contains the following
+ <p>A supervisor report is issued when a supervised child terminates
+ unexpectedly. A supervisor report contains the following
items:</p>
<taglist>
- <tag>Supervisor.</tag>
- <item>The name of the reporting supervisor.</item>
- <tag>Context.</tag>
- <item>Indicates in which phase the child terminated
+ <tag><c>Supervisor</c></tag>
+ <item><p>Name of the reporting supervisor.</p></item>
+ <tag><c>Context</c></tag>
+ <item><p>Indicates in which phase the child terminated
from the supervisor's point of view. This can be
- <c>start_error</c>, <c>child_terminated</c>, or
- <c>shutdown_error</c>.</item>
- <tag>Reason.</tag>
- <item>The termination reason.</item>
- <tag>Offender.</tag>
- <item>The start specification for the child.</item>
+ <c>start_error</c>, <c>child_terminated</c>, or
+ <c>shutdown_error</c>.</p></item>
+ <tag><c>Reason</c></tag>
+ <item><p>Termination reason.</p></item>
+ <tag><c>Offender</c></tag>
+ <item><p>Start specification for the child.</p></item>
</taglist>
</section>
<section>
<title>Progress Report</title>
- <p>A progress report is issued whenever a supervisor starts or
- restarts. A progress report contains the following items:</p>
+ <p>A progress report is issued when a supervisor starts or
+ restarts a child. A progress report contains the following items:</p>
<taglist>
- <tag>Supervisor.</tag>
- <item>The name of the reporting supervisor.</item>
- <tag>Started.</tag>
- <item>The start specification for the successfully
- started child.</item>
+ <tag><c>Supervisor</c></tag>
+ <item><p>Name of the reporting supervisor.</p></item>
+ <tag><c>Started</c></tag>
+ <item><p>Start specification for the successfully
+ started child.</p></item>
</taglist>
<marker id="CRASH"></marker>
</section>
<section>
<title>Crash Report</title>
- <p>Processes started with the <c>proc_lib:spawn</c> or
- <c>proc_lib:spawn_link</c> functions are wrapped within a
- <c>catch</c>. A crash report is issued whenever such a process
- terminates with an unexpected reason, which is any reason other
- than <c>normal</c> or <c>shutdown</c>. Processes using the
- <c>gen_server</c> and <c>gen_fsm</c> behaviours are examples of
- such processes. A crash report contains the following items:</p>
+ <p>Processes started with functions
+ <seealso marker="stdlib:proc_lib#spawn/1"><c>proc_lib:spawn</c></seealso> or
+ <seealso marker="stdlib:proc_lib#spawn_link/1"><c>proc_lib:spawn_link</c></seealso>
+ are wrapped within a <c>catch</c>. A crash report is issued when such
+ a process terminates with an unexpected reason, which is any reason
+ other than <c>normal</c>, <c>shutdown</c>, or <c>{shutdown,Term}</c>.
+ Processes using behaviors
+ <seealso marker="stdlib:gen_server"><c>gen_server</c></seealso> or
+ <seealso marker="stdlib:gen_fsm"><c>gen_fsm</c></seealso>
+ are examples of such processes. A crash report contains the following items:</p>
<taglist>
- <tag>Crasher.</tag>
- <item>Information about the crashing process is reported, such
- as initial function call, exit reason, and message queue.</item>
- <tag>Neighbours.</tag>
- <item>Information about processes which are linked to the crashing
+ <tag><c>Crasher</c></tag>
+ <item><p>Information about the crashing process, such
+ as initial function call, exit reason, and message queue.</p></item>
+ <tag><c>Neighbours</c></tag>
+ <item><p>Information about processes that are linked to the crashing
process and do not trap exits. These processes are the
- neighbours which will terminate because of this process
+ neighbours that terminate because of this process
crash. The information gathered is the same as the information
- for Crasher, shown in the previous item.</item>
+ for Crasher, described in the previous item.</p></item>
</taglist>
<section>
- <title>An Example</title>
- <p>The following example shows the reports which are generated
- when a process crashes. The example process is an
+ <title>Example</title>
+ <p>The following example shows the reports generated
+ when a process crashes. The example process is a
<c>permanent</c> process supervised by the <c>test_sup</c>
supervisor. A division by zero is executed and the error is
first reported by the faulty process. A crash report is
- generated as the process was started using the
- <c>proc_lib:spawn/3</c> function. The supervisor generates a
- supervisor report showing the process that has crashed, and then a
+ generated, as the process was started using function
+ <seealso marker="stdlib:proc_lib#spawn/3"><c>proc_lib:spawn/3</c></seealso>.
+ The supervisor generates a
+ supervisor report showing the crashed process. A
progress report is generated when the process is finally
- re-started.</p>
+ restarted.</p>
<pre>
=ERROR REPORT==== 27-May-1996::13:38:56 ===
&lt;0.63.0>: Divide by zero !
@@ -146,7 +150,6 @@
{shutdown,200},
{child_type,worker}]
-
=PROGRESS REPORT==== 27-May-1996::13:38:56 ===
Supervisor: {local,test_sup}
Started: [{pid,&lt;0.64.0>},
@@ -154,64 +157,66 @@
{mfa,{test,t,[]}},
{restart_type,permanent},
{shutdown,200},
- {child_type,worker}]
- </pre>
+ {child_type,worker}]</pre>
</section>
</section>
<section>
<title>Multi-File Error Report Logging</title>
- <p>Multi-file error report logging is used to store error messages,
- which are received by the <c>error_logger</c>. The error messages
+ <p>Multi-file error report logging is used to store error messages
+ received by <c>error_logger</c>. The error messages
are stored in several files and each file is smaller than a
- specified amount of kilobytes, and no more than a specified number
- of files exist at the same time. The logging is very fast because
+ specified number of kilobytes. No more than a specified number
+ of files exist at the same time. The logging is very fast, as
each error message is written as a binary term.</p>
- <p>Refer to
- <c>sasl</c> application in the Reference Manual for more details.</p>
+ <p>For more details, see the
+ <seealso marker="sasl_app"><c>sasl(6)</c></seealso>
+ application in the Reference Manual.</p>
</section>
<section>
<title>Report Browser</title>
<p>The report browser is used to browse and format error reports
- written by the error logger handler <c>log_mf_h</c> defined in
- <c>stdlib</c>.</p>
+ written by the error logger handler
+ <seealso marker="stdlib:log_mf_h"><c>log_mf_h</c></seealso>
+ defined in <c>STDLIB</c>.</p>
<p>The <c>log_mf_h</c> handler writes all reports to a
- report logging directory. This directory is specified when
- configuring the SASL application.</p>
+ report logging directory, which is specified when
+ configuring the <c>SASL</c> application.</p>
<p>If the report browser is
- used off-line, the reports can be copied to another directory
- which is specified when starting the browser. If no such directory
- is specified, the browser reads reports from the SASL
+ used offline, the reports can be copied to another directory
+ specified when starting the browser. If no such directory
+ is specified, the browser reads reports from the <c>SASL</c>
<c>error_logger_mf_dir</c>.</p>
<section>
- <title>Starting the Report Browser</title>
- <p>Start the <c>rb_server</c> with the function
- <c>rb:start([Options])</c> as shown in the following
- example:</p>
+ <title>Starting Report Browser</title>
+ <p>Start the <c>rb_server</c> with function
+ <seealso marker="rb#start/1"><c>rb:start([Options])</c></seealso>
+ as shown in the following example:</p>
<pre>
-
- 5><input>rb:start([{max, 20}]).</input>
+ 5> <input>rb:start([{max, 20}]).</input>
rb: reading report...done.
rb: reading report...done.
rb: reading report...done.
rb: reading report...done.
- </pre>
+ {ok,&lt;0.199.0>}</pre>
</section>
<section>
- <title>On-line Help</title>
- <p>Enter the command <em>rb:help().</em> to access the report
- browser on-line help system.</p>
+ <title>Online Help</title>
+ <p>Enter command
+ <seealso marker="rb#help/0"><c>rb:help()</c></seealso>
+ to access the report browser online help system.</p>
</section>
<section>
- <title>List Reports in the Server</title>
- <p>The function <c>rb:list()</c> lists all loaded reports:</p>
+ <title>List Reports in Server</title>
+ <p>Use function
+ <seealso marker="rb#list/0"><c>rb:list()</c></seealso>
+ to list all loaded reports:</p>
<pre>
-
- 4><input>rb:list().</input>
+ 4> <input>rb:list().</input>
No Type Process Date Time
== ==== ======= ==== ====
20 progress &lt;0.17.0> 1996-10-16 16:14:54
@@ -234,17 +239,15 @@
3 progress &lt;0.14.0> 1996-10-16 16:16:36
2 error &lt;0.15.0> 1996-10-16 16:17:04
1 progress &lt;0.14.0> 1996-10-16 16:17:09
- ok
- </pre>
+ ok</pre>
</section>
<section>
<title>Show Reports</title>
- <p>To show details of a specific report, use the function
- <c>rb:show(Number)</c>:</p>
+ <p>Use function
+ <seealso marker="rb#show/1"><c>rb:show(Number)</c></seealso>
+ to show details of a specific report:</p>
<pre>
-
-10> <input>rb:show(1).</input>
7> <input>rb:show(4).</input>
PROGRESS REPORT &lt;0.20.0> 1996-10-16 16:16:36
@@ -259,7 +262,7 @@ started
{child_type,worker}]
ok
-8> rb:show(9).
+8> <input>rb:show(9).</input>
CRASH REPORT &lt;0.24.0> 1996-10-16 16:16:21
===============================================================================
@@ -287,19 +290,17 @@ heap_size 610
stack_size 142
reductions 54
-ok
- </pre>
+ok</pre>
</section>
<section>
- <title>Search the Reports</title>
- <p>It is possible to show all reports which contain a common
- pattern. Suppose a process crashes because it tries to call a
- non-existing function <c>release_handler:mbj_func.</c> We could
- then show reports as follows:</p>
+ <title>Search Reports</title>
+ <p>All reports containing a common pattern can be shown.
+ Suppose a process crashes because it tries to call a
+ non-existing function <c>release_handler:mbj_func/1</c>.
+ The reports can then be shown as follows:</p>
<pre>
-
-12><input>rb:grep("mbj_func").</input>
+12> <input>rb:grep("mbj_func").</input>
Found match in report number 11
ERROR REPORT &lt;0.24.0> 1996-10-16 16:16:21
@@ -368,19 +369,17 @@ restart_type permanent
shutdown 2000
child_type worker
-ok
- </pre>
+ok</pre>
</section>
<section>
- <title>Stop the Server</title>
- <p>Stop the <c>rb_server</c> with the function
- <c>rb:stop()</c>:</p>
+ <title>Stop Server</title>
+ <p>Use function
+ <seealso marker="rb#stop/0"><c>rb:stop()</c></seealso>
+ to stop the <c>rb_server</c>:</p>
<pre>
-
-13><input>rb:stop().</input>
-ok
- </pre>
+13> <input>rb:stop().</input>
+ok</pre>
</section>
</section>
</chapter>
diff --git a/lib/sasl/doc/src/overload.xml b/lib/sasl/doc/src/overload.xml
index 35877220ab..5c3d00afeb 100644
--- a/lib/sasl/doc/src/overload.xml
+++ b/lib/sasl/doc/src/overload.xml
@@ -35,98 +35,88 @@
<module>overload</module>
<modulesummary>An Overload Regulation Process</modulesummary>
<description>
- <p><c>overload</c> is a process which indirectly regulates CPU
+ <p><c>overload</c> is a process that indirectly regulates the CPU
usage in the system. The idea is that a main application calls
- the <c>request/0</c> function before starting a major job, and
+ function
+ <seealso marker="#request/0"><c>request/0</c></seealso>
+ before starting a major job and
proceeds with the job if the return value is positive; otherwise
- the job must not be started.
- </p>
- <p><c>overload</c> is part of the <c>sasl</c> application, and all
- configuration parameters are defined there.
- </p>
- <p>A set of two intensities are maintained, the <c>total intensity</c> and the <c>accept intensity</c>. For that purpose
- there are two configuration parameters, the <c>MaxIntensity</c>
- and the <c>Weight</c> value (both are measured in 1/second).
- </p>
+ the job must not be started.</p>
+ <p><c>overload</c> is part of the <c>SASL</c> application and all
+ configuration parameters are defined there.</p>
+ <p>A set of two intensities are maintained, the <c>total intensity</c>
+ and the <c>accept intensity</c>. For that purpose,
+ there are two configuration parameters, <c>MaxIntensity</c>
+ and <c>Weight</c>; both are measured in 1/second.</p>
<p>Then total and accept intensities are calculated as
follows. Assume that the time of the current call to
- <c>request/0</c> is <c>T(n)</c>, and that the time of the
- previous call was <c>T(n-1)</c>.
- </p>
+ <c>request/0</c> is <c>T(n)</c> and that the time of the
+ previous call was <c>T(n-1)</c>.</p>
<list type="bulleted">
<item>
<p>The current <c>total intensity</c>, denoted
- <c>TI(n)</c>, is calculated according to the formula,
- </p>
- <p><c>TI(n) = exp(-Weight*(T(n) - T(n-1)) * TI(n-1) + Weight</c>,
- </p>
- <p>where <c>TI(n-1)</c> is the previous total intensity.
- </p>
+ <c>TI(n)</c>, is calculated according to the formula</p>
+ <p><c>TI(n) = exp(-Weight*(T(n) - T(n-1)) * TI(n-1) + Weight</c>,</p>
+ <p>where <c>TI(n-1)</c> is the previous <c>total intensity</c>.</p>
</item>
<item>
<p>The current <c>accept intensity</c>, denoted
- <c>AI(n)</c>, is determined by the formula,
- </p>
- <p><c>AI(n) = exp(-Weight*(T(n) - T(n-1)) * AI(n-1) + Weight</c>,
- </p>
- <p>where <c>AI(n-1)</c> is the previous accept intensity,
- provided that the value of <c>exp(-Weight*(T(n) - T(n-1)) * AI(n-1)</c> is less than <c>MaxIntensity</c>; otherwise the
- value is
- </p>
- <p><c>AI(n) = exp(-Weight*(T(n) - T(n-1)) * AI(n-1)</c>.
- </p>
+ <c>AI(n)</c>, is determined by the formula</p>
+ <p><c>AI(n) = exp(-Weight*(T(n) - T(n-1)) * AI(n-1) + Weight</c>,</p>
+ <p>where <c>AI(n-1)</c> is the previous <c>accept intensity</c>,
+ if the value of <c>exp(-Weight*(T(n) - T(n-1)) * AI(n-1)</c>
+ is less than <c>MaxIntensity</c>. Otherwise the value is</p>
+ <p><c>AI(n) = exp(-Weight*(T(n) - T(n-1)) * AI(n-1)</c></p>
</item>
</list>
<p>The value of configuration parameter <c>Weight</c> controls the
- speed with which the calculations of intensities will react to
+ speed with which the calculations of intensities react to
changes in the underlying input intensity. The inverted value of
- <c>Weight</c>,
- </p>
- <p><c>T = 1/Weight</c></p>
- <p>can be thought of as the "time constant"
- of the intensity calculation formulas. For example, if <c>Weight = 0.1</c>, then a change in the underlying input intensity will be
- reflected in the <c>total</c> and <c>accept intensities</c> within
- approximately 10 seconds.
- </p>
+ <c>Weight</c>, <c>T = 1/Weight</c>, can be thought of as the
+ "time constant" of the intensity calculation formulas. For example,
+ if <c>Weight = 0.1</c>, a change in the underlying input intensity is
+ reflected in <c>total intensity</c> and <c>accept intensity</c> within
+ about 10 seconds.</p>
<p>The overload process defines one alarm, which it sets using
- <c>alarm_handler:set_alarm(Alarm)</c>. <c>Alarm</c> is defined
- as:
- </p>
+ <c>alarm_handler:set_alarm(Alarm)</c>. <c>Alarm</c> is defined
+ as follows:</p>
<taglist>
<tag><c>{overload, []}</c></tag>
<item>
- <p>This alarm is set when the current accept intensity exceeds
- <c>MaxIntensity</c>.
- </p>
+ <p>This alarm is set when the current <c>accept intensity</c> exceeds
+ <c>MaxIntensity</c>.</p>
</item>
</taglist>
- <p>A new overload alarm is not set until the current accept
- intensity has fallen below <c>MaxIntensity</c>. To prevent the
- overload process from generating a lot of set/reset alarms, the
- alarm is not reset until the current accept intensity has fallen
- below 75% of <c>MaxIntensity</c>, and it is not until then that
- the alarm can be set again.
- </p>
+ <p>A new request is not accepted until the current <c>accept
+ intensity</c> has fallen below <c>MaxIntensity</c>. To prevent the
+ overload process from generating many set/reset alarms, the
+ alarm is not reset until the current <c>accept intensity</c> has fallen
+ below 75% of <c>MaxIntensity</c>; it is not until then that
+ the alarm can be set again.</p>
</description>
+
<funcs>
<func>
<name>request() -> accept | reject</name>
- <fsummary>Request to proceed with current job</fsummary>
+ <fsummary>Requests to proceed with current job.</fsummary>
<desc>
<p>Returns <c>accept</c> or <c>reject</c> depending on the
- current value of the accept intensity. </p>
+ current value of the <c>accept intensity</c>.</p>
<p>The application
- calling this function should be processed with the job in
+ calling this function is to proceed with the job in
question if the return value is <c>accept</c>; otherwise it
- should not continue with that job.
- </p>
+ is not to continue with that job.</p>
</desc>
</func>
+
<func>
<name>get_overload_info() -> OverloadInfo</name>
- <fsummary>Return current overload information data</fsummary>
+ <fsummary>Returns current overload information data.</fsummary>
<type>
- <v>OverloadInfo = [{total_intensity, TotalIntensity}, {accept_intensity, AcceptIntensity}, {max_intensity, MaxIntensity}, {weight, Weight}, {total_requests, TotalRequests}, {accepted_requests, AcceptedRequests}].</v>
+ <v>OverloadInfo = [{total_intensity, TotalIntensity},
+ {accept_intensity, AcceptIntensity}, {max_intensity,
+ MaxIntensity}, {weight, Weight}, {total_requests,
+ TotalRequests}, {accepted_requests, AcceptedRequests}].</v>
<v>TotalIntensity = float() > 0</v>
<v>AcceptIntensity = float() > 0</v>
<v>MaxIntensity = float() > 0</v>
@@ -135,18 +125,22 @@
<v>AcceptedRequests = integer()</v>
</type>
<desc>
- <p>Returns the current total and accept intensities, the
- configuration parameters, and absolute counts of the total
- number of requests, and accepted number of requests (since
- the overload process was started).</p>
+ <p>Returns:</p>
+ <list type="bulleted">
+ <item>Current total and accept intensities</item>
+ <item>Configuration parameters</item>
+ <item>Absolute counts of the total number of requests</item>
+ <item>Accepted number of requests (since the overload
+ process was started)</item>
+ </list>
</desc>
</func>
</funcs>
<section>
<title>See Also</title>
- <p>alarm_handler(3), sasl(3)
- </p>
+ <p><seealso marker="alarm_handler"><c>alarm_handler(3)</c></seealso>,
+ <seealso marker="sasl_app"><c>sasl(6)</c></seealso></p>
</section>
</erlref>
diff --git a/lib/sasl/doc/src/part.xml b/lib/sasl/doc/src/part.xml
index bcd345a7c4..2f47a8ad80 100644
--- a/lib/sasl/doc/src/part.xml
+++ b/lib/sasl/doc/src/part.xml
@@ -30,8 +30,9 @@
<file>part.xml</file>
</header>
<description>
- <p>The System Architecture Support Libraries, <em>SASL</em>,
- provides support for alarm and release handling etc.</p>
+ <p>The System Architecture Support Libraries <c>SASL</c> application
+ provides support for alarm handling, release handling, and
+ related functions.</p>
</description>
<xi:include href="sasl_intro.xml"/>
<xi:include href="error_logging.xml"/>
diff --git a/lib/sasl/doc/src/rb.xml b/lib/sasl/doc/src/rb.xml
index 85252fc088..e16e9f5a62 100644
--- a/lib/sasl/doc/src/rb.xml
+++ b/lib/sasl/doc/src/rb.xml
@@ -35,241 +35,252 @@
<module>rb</module>
<modulesummary>The Report Browser Tool</modulesummary>
<description>
- <p>The Report Browser (RB) tool makes it possible to browse and
+ <p>The Report Browser (RB) tool is used to browse and
format error reports written by the error logger handler
- <c>log_mf_h</c>.
- </p>
+ <seealso marker="stdlib:log_mf_h"><c>log_mf_h</c></seealso>
+ in <c>STDLIB</c>.</p>
</description>
+
<funcs>
<func>
<name>filter(Filters)</name>
<name>filter(Filters, Dates)</name>
- <fsummary>Filter reports and displays them on the screen</fsummary>
+ <fsummary>Filters reports and displays them on the screen.</fsummary>
<type>
<v>Filters = [filter()]</v>
- <v>filter() = {Key, Value} | {Key, Value, no} | {Key, RegExp, re} | {Key, RegExp, re, no}</v>
+ <v>filter() = {Key, Value} | {Key, Value, no} | {Key, RegExp, re} |
+ {Key, RegExp, re, no}</v>
<v>Key = term()</v>
<v>Value = term()</v>
- <v>RegExp = string() | {string, Options} | mp(), {mp(), Options}</v>
+ <v>RegExp = string() | {string(), Options} | re:mp() | {re:mp(), Options}</v>
<v>Dates = {DateFrom, DateTo} | {DateFrom, from} | {DateTo, to}</v>
- <v>DateFrom = DateTo = {date(), time()}</v>
- <v>date() and time() are the same type as in the <c>calendar</c> module</v>
+ <v>DateFrom = DateTo = calendar:datetime()</v>
</type>
<desc>
- <p>This function displays the reports that match the provided filters.</p>
- <p>
- When a filter includes the <c>no</c> atom it will exclude the reports that match
- that filter.
- </p>
- <p>
- The reports are matched using the <c>proplists</c> module. The report must be a proplist
- to be matched against any of the <c>filters()</c>.
- </p>
- <p>
- If the filter is of the form <c>{Key, RegExp, re}</c> the report must contain an element with
- <c>key = Key</c> and <c>Value</c> must match the RegExp regular expression.
- </p>
- <p>
- If the Dates parameter is provided, then the reports are filtered according to the date
- when they occurred. If Dates is of the form <c>{DateFrom, from}</c> then reports that occurred
- after DateFrom are displayed.
- </p>
- <p>
- If Dates is of the form <c>{DateTo, to}</c> then reports that occurred before DateTo
- are displayed.
- </p>
- <p>
- If two Dates are provided, then reports that occurred between those dates are returned.
- </p>
- <p>
- If you only want to filter only by dates, then you can provide the empty list as the Filters
- parameter.
- </p>
- <p>
- See <c>rb:grep/1</c> for more information on the RegExp parameter.
- </p>
+ <p>Displays the reports that match the provided filters.</p>
+ <p>When a filter includes the <c>no</c> atom, it excludes the
+ reports that match that filter.</p>
+ <p>The reports are matched using the
+ <seealso marker="stdlib:proplists"><c>proplists</c></seealso>
+ module in <c>STDLIB</c>. The report must be a proplist
+ to be matched against any of the filters.</p>
+ <p>If the filter has the form <c>{Key, RegExp, re}</c>, the
+ report must contain an element with key equal to <c>Key</c> and
+ the value must match the regular expression <c>RegExp</c>.</p>
+ <p>If parameter <c>Dates</c> is specified, the reports are filtered
+ according to the date when they occurred. If <c>Dates</c> has
+ the form <c>{DateFrom, from}</c>, reports that occurred after
+ <c>DateFrom</c> are displayed.</p>
+ <p>If <c>Dates</c> has the form <c>{DateTo, to}</c>, reports that
+ occurred before <c>DateTo</c> are displayed.</p>
+ <p>If two <c>Dates</c> are specified, reports that occurred between
+ those dates are returned.</p>
+ <p>To filter only by dates, specify the empty list as the <c>Filters</c>
+ parameter.</p>
+ <p>For details about parameter <c>RegExp</c>, see <c>rb:grep/1</c>.</p>
+ <p>For details about data type <c>mp()</c>, see
+ <seealso marker="stdlib:re#type-mp"><c>re:mp()</c></seealso>.</p>
+ <p>For details about data type <c>datetime()</c>, see
+ <seealso marker="stdlib:calendar#type-datetime"><c>calendar:datetime()</c></seealso>.</p>
</desc>
</func>
+
<func>
<name>grep(RegExp)</name>
- <fsummary>Search the reports for a regular expression</fsummary>
+ <fsummary>Searches the reports for a regular expression.</fsummary>
<type>
- <v>RegExp = string() | {string, Options} | mp(), {mp(), Options}</v>
+ <v>RegExp = string() | {string(), Options} | re:mp() | {re:mp(), Options}</v>
</type>
<desc>
- <p>All reports containing the regular expression <c>RegExp</c>
- are printed.
- </p>
- <p><c>RegExp</c> can be a string containing the regular
- expression; a tuple with the string and the options for
- compilation; a compiled regular expression; a compiled
- regular expression and the options for running it.
- Refer to the module <c>re</c> and specially the function <c>re:run/3</c>
- for a definition of valid regular expressions and options.
- </p>
+ <p>All reports matching the regular expression <c>RegExp</c>
+ are displayed. <c>RegExp</c> can be any of the following:</p>
+ <list type="bulleted">
+ <item>A string containing the regular expression</item>
+ <item>A tuple with the string and the options for compilation</item>
+ <item>A compiled regular expression</item>
+ <item>A compiled regular expression and the options for running it</item>
+ </list>
+ <p>For a definition of valid regular expressions and options, see
+ the <seealso marker="stdlib:re"><c>re</c></seealso> module in
+ <c>STDLIB</c> and in particular function <c>re:run/3</c>.</p>
+ <p>For details about data type <c>mp()</c>, see
+ <seealso marker="stdlib:re#type-mp"><c>re:mp()</c></seealso>.</p>
</desc>
</func>
+
<func>
<name>h()</name>
<name>help()</name>
- <fsummary>Print help information</fsummary>
+ <fsummary>Displays help information.</fsummary>
<desc>
- <p>Prints the on-line help information.
- </p>
+ <p>Displays online help information.</p>
</desc>
</func>
+
<func>
<name>list()</name>
<name>list(Type)</name>
- <fsummary>List all reports</fsummary>
+ <fsummary>Lists all reports.</fsummary>
<type>
<v>Type = type()</v>
<v>type() = error | error_report | info_msg | info_report |
- warning_msg | warning_report | crash_report |
- supervisor_report | progress</v>
+ warning_msg | warning_report | crash_report |
+ supervisor_report | progress</v>
</type>
<desc>
- <p>This function lists all reports loaded in the
+ <p>Lists all reports loaded in
<c>rb_server</c>. Each report is given a unique number that
- can be used as a reference to the report in the
- <c>show/1</c> function.
- </p>
- <p>If no <c>Type</c> is given, all reports are listed.
- </p>
+ can be used as a reference to the report in function
+ <seealso marker="#show/1"><c>show/1</c></seealso>.</p>
+ <p>If no <c>Type</c> is specified, all reports are listed.</p>
</desc>
</func>
+
<func>
<name>log_list()</name>
<name>log_list(Type)</name>
- <fsummary>Log reports list</fsummary>
+ <fsummary>Logs report lists.</fsummary>
<type>
<v>Type = type()</v>
<v>type() = error | error_report | info_msg | info_report |
- warning_msg | warning_report | crash_report |
- supervisor_report | progress</v>
+ warning_msg | warning_report | crash_report |
+ supervisor_report | progress</v>
</type>
<desc>
- <p>Same as <c>list/0</c> or <c>list/1</c> functions
- but result is printed to logfile, if set, otherwise to standard_io.
- </p>
- <p>If no <c>Type</c> is given, all reports are listed.
- </p>
+ <p>Same as functions
+ <seealso marker="#list/0"><c>list/0</c></seealso> or
+ <seealso marker="#list/1"><c>list/1</c></seealso>,
+ but the result is printed to a log file, if set; otherwise
+ to <c>standard_io</c>.</p>
+ <p>If no <c>Type</c> is specified, all reports are listed.</p>
</desc>
</func>
+
<func>
<name>rescan()</name>
<name>rescan(Options)</name>
- <fsummary>Rescan the report directory</fsummary>
+ <fsummary>Rescans the report directory.</fsummary>
<type>
<v>Options = [opt()]</v>
</type>
<desc>
<p>Rescans the report directory. <c>Options</c> is the same as
- for <c>start()</c>.
- </p>
+ for function
+ <seealso marker="#start/1"><c>start/1</c></seealso>.</p>
</desc>
</func>
+
<func>
<name>show()</name>
<name>show(Report)</name>
- <fsummary>Show reports</fsummary>
+ <fsummary>Displays reports.</fsummary>
<type>
- <v>Report = int() | type()</v>
+ <v>Report = integer() | type()</v>
</type>
<desc>
- <p>If a type argument is given, all loaded reports of this
- type are printed. If an integer argument is given, the
- report with this reference number is printed. If no argument
- is given, all reports are shown.
- </p>
+ <p>If argument <c>type</c> is specified, all loaded reports of this
+ type are displayed. If an integer argument is specified, the
+ report with this reference number is displayed. If no argument
+ is specified, all reports are displayed.</p>
</desc>
</func>
+
<func>
<name>start()</name>
<name>start(Options)</name>
- <fsummary>Start the RB server</fsummary>
+ <fsummary>Starts the <c>rb_server</c>.</fsummary>
<type>
<v>Options = [opt()]</v>
- <v>opt() = {start_log, FileName} | {max, MaxNoOfReports} | {report_dir, DirString} | {type, ReportType} | {abort_on_error, Bool}</v>
+ <v>opt() = {start_log, FileName} | {max, MaxNoOfReports} |
+ {report_dir, DirString} | {type, ReportType} |
+ {abort_on_error, Bool}</v>
<v>FileName = string() | atom() | pid()</v>
- <v>MaxNoOfReports = int() | all</v>
+ <v>MaxNoOfReports = integer() | all</v>
<v>DirString = string()</v>
<v>ReportType = type() | [type()] | all</v>
- <v>Bool = true | false</v>
+ <v>Bool = boolean()</v>
</type>
<desc>
- <p>The function <c>start/1</c> starts the <c>rb_server</c>
- with the specified options, while <c>start/0</c> starts with
- default options. The <c>rb_server</c> must be started before
- reports can be browsed. When the <c>rb_server</c> is
+ <p>Function <c>start/1</c> starts <c>rb_server</c> with the
+ specified options, whereas function <c>start/0</c> starts with
+ default options. <c>rb_server</c> must be started before
+ reports can be browsed. When <c>rb_server</c> is
started, the files in the specified directory are
scanned. The other functions assume that the server has
- started.
- </p>
- <p><c>{start_log, FileName}</c> starts logging to file,
- registered name or io_device. All reports will be printed
- to the named file. The default is <c>standard_io</c>.
- The option {start_log, standard_error} is not allowed and
- will be replaced by default standard_io.
- </p>
- <p><c>{max, MaxNoOfReports}</c>. Controls how many reports the
- <c>rb_server</c> should read on start-up. This option is
- useful as the directory may contain 20.000 reports. If this
- option is given, the <c>MaxNoOfReports</c> latest reports
- will be read. The default is 'all'.
- </p>
- <p><c>{report_dir, DirString}</c>. Defines the directory where
- the error log files are located. The default is <c>{sasl, error_logger_mf_dir}</c>. </p>
- <p><c>{type, ReportType}</c>. Controls what kind of reports the
- <c>rb_server</c> should read on start-up. <c>ReportType</c>
- is a supported type, 'all', or a list of supported
- types. The default is 'all'.
- </p>
- <p><c>{abort_on_error, Bool}</c>. This option specifies whether
- or not logging should be aborted if rb encounters an unprintable
- report. (You may get a report on incorrect form if the
- <c>error_logger</c> function <c>error_msg</c> or
- <c>info_msg</c> has been called with an invalid format string).
- If <c>Bool</c> is <c>true</c>, rb will stop logging (and print an
- error message to stdout) if it encounters a badly formatted report.
- If logging to file is enabled, an error message will be appended to
- the log file as well.
- If <c>Bool</c> is <c>false</c> (which is the default value), rb will
- print an error message to stdout for every bad report it
- encounters, but the logging process is never aborted. All printable
- reports will be written. If logging to file is enabled, rb prints
- <c>* UNPRINTABLE REPORT *</c> in the log file at the location of an
- unprintable report.
- </p>
+ started.</p>
+ <p><em>Options:</em></p>
+ <taglist>
+ <tag><c>{start_log, FileName}</c></tag>
+ <item><p>Starts logging to file,
+ registered name, or <c>io_device</c>. All reports are printed
+ to the specified destination. Default is <c>standard_io</c>.
+ Option <c>{start_log, standard_error}</c> is not allowed and
+ will be replaced by default <c>standard_io</c>.</p></item>
+ <tag><c>{max, MaxNoOfReports}</c></tag>
+ <item><p>Controls how many reports
+ <c>rb_server</c> is to read at startup. This option is
+ useful, as the directory can contain a large amount of reports. If this
+ option is specified, the <c>MaxNoOfReports</c> latest reports
+ are read. Default is <c>all</c>.</p></item>
+ <tag><c>{report_dir, DirString}</c></tag>
+ <item><p>Defines the directory where
+ the error log files are located. Default is
+ the directory specified by application environment
+ variable <c>error_logger_mf_dir</c>,
+ see <seealso marker="sasl_app">sasl(6)</seealso>.</p></item>
+ <tag><c>{type, ReportType}</c></tag>
+ <item><p>Controls what kind of reports
+ <c>rb_server</c> is to read at startup. <c>ReportType</c>
+ is a supported type, <c>all</c>, or a list of supported
+ types. Default is <c>all</c>.</p></item>
+ <tag><c>{abort_on_error, Bool}</c></tag>
+ <item><p>Specifies if
+ logging is to be ended if <c>rb</c> encounters an unprintable
+ report. (You can get a report with an incorrect form if function
+ <c>error_logger</c>, <c>error_msg</c>, or
+ <c>info_msg</c> has been called with an invalid format string)</p>
+ <list type="bulleted">
+ <item>If <c>Bool</c> is <c>true</c>, <c>rb</c> stops logging
+ (and prints an error message to <c>stdout</c>) if it encounters
+ a badly formatted report. If logging to file is enabled, an
+ error message is appended to the log file as well.</item>
+ <item>If <c>Bool</c> is <c>false</c> (the default value), <c>rb</c>
+ prints an error message to <c>stdout</c> for every bad report it
+ encounters, but the logging process is never ended. All printable
+ reports are written. If logging to file is enabled, <c>rb</c> prints
+ <c>* UNPRINTABLE REPORT *</c> in the log file at the location of an
+ unprintable report.</item>
+ </list></item>
+ </taglist>
</desc>
</func>
+
<func>
<name>start_log(FileName)</name>
- <fsummary>Redirect all output to <c>FileName</c></fsummary>
+ <fsummary>Redirects all output to <c>FileName</c>.</fsummary>
<type>
<v>FileName = string() | atom() | pid()</v>
</type>
<desc>
<p>Redirects all report output from the RB tool to the
- specified file, registered name or io_device.
- </p>
+ specified file, registered name, or <c>io_device</c>.</p>
</desc>
</func>
+
<func>
<name>stop()</name>
- <fsummary>Stop the RB server</fsummary>
+ <fsummary>Stops the <c>rb_server</c>.</fsummary>
<desc>
- <p>Stops the <c>rb_server</c>.
- </p>
+ <p>Stops <c>rb_server</c>.</p>
</desc>
</func>
+
<func>
<name>stop_log()</name>
- <fsummary>Stop logging to file</fsummary>
+ <fsummary>Stops logging to file.</fsummary>
<desc>
- <p>Closes the log file. The output from the RB tool will be
- directed to <c>standard_io</c>.
- </p>
+ <p>Closes the log file. The output from the RB tool is
+ directed to <c>standard_io</c>.</p>
</desc>
</func>
</funcs>
diff --git a/lib/sasl/doc/src/ref_man.xml b/lib/sasl/doc/src/ref_man.xml
index 2b608c7c51..a80e5a2a00 100644
--- a/lib/sasl/doc/src/ref_man.xml
+++ b/lib/sasl/doc/src/ref_man.xml
@@ -30,8 +30,8 @@
<file>application.xml</file>
</header>
<description>
- <p>The System Architecture Support Libraries application, <em>SASL</em>,
- provides support for alarm and release handling etc.</p>
+ <p>The <c>SASL</c> application provides support for alarm handling,
+ release handling, and related functions.</p>
</description>
<xi:include href="sasl_app.xml"/>
<xi:include href="alarm_handler.xml"/>
diff --git a/lib/sasl/doc/src/rel.xml b/lib/sasl/doc/src/rel.xml
index a16db24295..d5f3c7310a 100644
--- a/lib/sasl/doc/src/rel.xml
+++ b/lib/sasl/doc/src/rel.xml
@@ -33,74 +33,65 @@
<file>rel</file>
<filesummary>Release resource file</filesummary>
<description>
- <p>The <em>release resource file</em> specifies which applications are
+ <p>The <em>release resource file</em> specifies which applications
are included in a release (system) based on Erlang/OTP.</p>
- <p>This file is used by the functions in <c>systools</c> when generating
- start scripts (<c>.script</c>, <c>.boot</c>) and release upgrade
- files (<c>relup</c>).</p>
+ <p>This file is used by the functions in
+ <seealso marker="systools"><c>systools</c></seealso>
+ when generating start scripts (<c>.script</c>, <c>.boot</c>) and
+ release upgrade files (<c>relup</c>).</p>
</description>
<section>
- <title>FILE SYNTAX</title>
- <p>The release resource file should be called <c>Name.rel</c>.</p>
+ <title>File Syntax</title>
+ <p>The release resource file is to be called <c>Name.rel</c>.</p>
<p>The <c>.rel</c> file contains one single Erlang term, which is
- called a <em>release specification</em>. The file has the
+ called a <em>release specification</em>. The file has the
following syntax:</p>
<code type="none">
{release, {RelName,Vsn}, {erts, EVsn},
[{Application, AppVsn} |
{Application, AppVsn, Type} |
{Application, AppVsn, IncApps} |
- {Application, AppVsn, Type, IncApps}]}.
- </code>
- <list type="bulleted">
- <item>
- <p><c>RelName = string()</c> is the name of the release.</p>
- </item>
- <item>
- <p><c>Vsn = string()</c> is the version of the release.</p>
- </item>
- <item>
- <p><c>EVsn = string()</c> is the version of ERTS the release is
- intended for.</p>
- </item>
- <item>
- <p><c>Application = atom()</c> is the name of an application
- included in the release.</p>
- </item>
- <item>
- <p><c>AppVsn = string()</c> is the version of an application
- included in the release.</p>
- </item>
- <item>
- <p><c>Type = permanent | transient | temporary | load | none</c>
- is the start type of an application included in the release.</p>
- <p>If <c>Type = permanent | transient | temporary</c>,
- the application will be loaded and started in the corresponding
- way, see <c>application(3)</c>. If <c>Type = load</c>,
- the application will only be loaded. If <c>Type = none</c>,
- the application will be neither loaded nor started, although
- the code for its modules will be loaded.
- Defaults to <c>permanent</c></p>
- </item>
- <item>
- <p><c>IncApps = [atom()]</c> is a list of applications that are
- included by an application included in the release.</p>
- <p>The list must be a subset of the included applications
+ {Application, AppVsn, Type, IncApps}]}.</code>
+ <taglist>
+ <tag><c>RelName = string()</c></tag>
+ <item><p>Release name.</p></item>
+ <tag><c>Vsn = string()</c></tag>
+ <item><p>Release version.</p></item>
+ <tag><c>EVsn = string()</c></tag>
+ <item><p><c>ERTS</c> version the release is intended for.</p></item>
+ <tag><c>Application = atom()</c></tag>
+ <item><p>Name of an application included in the release.</p></item>
+ <tag><c>AppVsn = string()</c></tag>
+ <item><p>Version of an application included in the release.</p></item>
+ <tag><c>Type = permanent | transient | temporary | load | none</c></tag>
+ <item><p>Start type of an application included in the release.</p>
+ <p>If <c>Type = permanent | transient | temporary</c>, the
+ application is loaded and started in the corresponding way, see
+ <seealso marker="kernel:application"><c>application(3)</c></seealso>.</p>
+ <p>If <c>Type = load</c>, the application is only loaded.</p>
+ <p>If <c>Type = none</c>, the application is not loaded and not
+ started, although the code for its modules is loaded.</p>
+ <p>Defaults to <c>permanent</c></p></item>
+ <tag><c>IncApps = [atom()]</c></tag>
+ <item><p>A list of applications that are included by an application
+ included in the release. The list must be a subset of the
+ included applications
specified in the application resource file
(<c>Application.app</c>) and overrides this value. Defaults
- to the same value as in the application resource file.</p>
- </item>
- </list>
+ to the same value as in the application resource file.</p></item>
+ </taglist>
<note>
- <p>The list of applications must contain the <c>kernel</c> and
- <c>stdlib</c> applications.</p>
+ <p>The list of applications must contain the <c>Kernel</c> and
+ <c>STDLIB</c> applications.</p>
</note>
</section>
<section>
- <title>SEE ALSO</title>
- <p>application(3), relup(4), systools(3)</p>
+ <title>See Also</title>
+ <p><seealso marker="kernel:application"><c>application(3)</c></seealso>,
+ <seealso marker="relup"><c>relup(4)</c></seealso>,
+ <seealso marker="systools"><c>systools(3)</c></seealso></p>
</section>
</fileref>
diff --git a/lib/sasl/doc/src/release_handler.xml b/lib/sasl/doc/src/release_handler.xml
index 692159d7bf..162707676c 100644
--- a/lib/sasl/doc/src/release_handler.xml
+++ b/lib/sasl/doc/src/release_handler.xml
@@ -31,109 +31,115 @@
<module>release_handler</module>
<modulesummary>Unpacking and Installation of Release Packages</modulesummary>
<description>
- <p>The <em>release handler</em> is a process belonging to the SASL
- application which is responsible for <em>release handling</em>,
+ <p>The <em>release handler</em> process belongs to the <c>SASL</c>
+ application, which is responsible for <em>release handling</em>,
that is, unpacking, installation, and removal of release packages.</p>
- <p>An introduction to release handling and a usage example can be
- found in
- <seealso marker="doc/design_principles:release_handling">Design Principles</seealso>.
- </p>
+ <p>An introduction to release handling and an example is provided in
+ <seealso marker="doc/design_principles:release_handling">OTP Design
+ Principles</seealso> in <em>System Documentation</em>.</p>
<p>A <em>release package</em> is a compressed tar file containing
code for a certain version of a release, created by calling
- <seealso marker="systools#make_tar/1">systools:make_tar/1,2</seealso>.
- The release package should be placed in the <c>$ROOT/releases</c>
- directory of the previous version of the release where
+ <seealso marker="systools#make_tar/1"><c>systools:make_tar/1,2</c></seealso>.
+ The release package is to be located in the <c>$ROOT/releases</c>
+ directory of the previous version of the release, where
<c>$ROOT</c> is the installation root directory,
- <c>code:root_dir()</c>.
- Another <c>releases</c> directory can be specified using the SASL
- configuration parameter <c>releases_dir</c>, or the OS environment
+ <seealso marker="kernel:code#root_dir/0"><c>code:root_dir()</c></seealso>.
+ Another <c>releases</c> directory can be specified using the <c>SASL</c>
+ configuration parameter <c>releases_dir</c> or the OS environment
variable <c>RELDIR</c>. The release handler must have write access
- to this directory in order to install the new release.
+ to this directory to install the new release.
The persistent state of the release handler is stored there in a
file called <c>RELEASES</c>.</p>
- <p>A release package should always contain the release resource file
- <c>Name.rel</c> and a boot script <c>Name.boot</c>. It may contain
- a release upgrade file <c>relup</c> and a system configuration
- file <c>sys.config</c>. The <c>.rel</c> file contains information
- about the release: its name, version, and which ERTS and
- application versions it uses. The <c>relup</c> file contains
- scripts for how to upgrade to, or downgrade from, this version of
- the release.</p>
+ <p>A release package is always to contain:</p>
+ <list type="bulleted">
+ <item>A release resource file, <c>Name.rel</c></item>
+ <item>A boot script, <c>Name.boot</c></item>
+ </list>
+ <p>The <c>.rel</c> file contains information about the release: its name,
+ version, and which <c>ERTS</c> and application versions it uses.</p>
+ <p>A release package can also contain:</p>
+ <list type="bulleted">
+ <item>A release upgrade file, <c>relup</c></item>
+ <item>A system configuration file, <c>sys.config</c></item>
+ </list>
+ <p>The <c>relup</c> file contains instructions for how to upgrade
+ to, or downgrade from, this version of the release.</p>
<p>The release package can be <em>unpacked</em>, which extracts
the files. An unpacked release can be <em>installed</em>.
The currently used version of the release is then upgraded or
downgraded to the specified version by evaluating the instructions
- in <c>relup</c>. An installed release can be made
- <em>permanent</em>. There can only be one permanent release in
- the system, and this is the release that is used if the system
+ in the <c>relup</c> file. An installed release can be made
+ <em>permanent</em>. Only one permanent release can exist in
+ the system, and this release is used if the system
is restarted. An installed release, except the permanent one,
can be <em>removed</em>. When a release is removed, all files
- that belong to that release only are deleted.</p>
- <p>Each version of the release has a status. The status can be
+ belonging to that release only are deleted.</p>
+ <p>Each release version has a status, which can be
<c>unpacked</c>, <c>current</c>, <c>permanent</c>, or <c>old</c>.
- There is always one latest release which either has status
- <c>permanent</c> (normal case), or <c>current</c> (installed, but
- not yet made permanent). The following table illustrates
- the meaning of the status values:</p>
+ There is always one latest release, which either has status
+ <c>permanent</c> (normal case) or <c>current</c> (installed, but
+ not yet made permanent). The meaning of the status values are
+ illustrated in the following table:</p>
<pre>
-Status Action NextStatus
--------------------------------------------
- - unpack unpacked
-unpacked install current
- remove -
-current make_permanent permanent
- install other old
- remove -
-permanent make other permanent old
- install permanent
-old reboot_old permanent
- install current
- remove -
- </pre>
+ Status Action NextStatus
+ -------------------------------------------
+ - unpack unpacked
+ unpacked install current
+ remove -
+ current make_permanent permanent
+ install other old
+ remove -
+ permanent make other permanent old
+ install permanent
+ old reboot_old permanent
+ install current
+ remove -</pre>
<p>The release handler process is a locally registered process on
each node. When a release is installed in a distributed system,
the release handler on each node must be called. The release
- installation may be synchronized between nodes. From an operator
- view, it may be unsatisfactory to specify each node. The aim is
+ installation can be synchronized between nodes. From an operator
+ view, it can be unsatisfactory to specify each node. The aim is
to install one release package in the system, no matter how many
- nodes there are. If this is the case, it is recommended that
- software management functions are written which take care of
- this problem. Such a function may have knowledge of the system
+ nodes there are. It is recommended that
+ software management functions are written that take care of
+ this problem. Such a function can have knowledge of the system
architecture, so it can contact each individual release handler
to install the package.</p>
- <p>For release handling to work properly, the runtime system needs
- to have knowledge about which release it is currently running. It
- must also be able to change (in run-time) which boot script and
- system configuration file should be used if the system is
+ <p>For release handling to work properly, the runtime system must
+ know which release it is running. It
+ must also be able to change (in runtime) which boot script and
+ system configuration file are to be used if the system is
restarted. This is taken care of automatically if Erlang is
- started as an embedded system. Read about this in <em>Embedded System</em>. In this case, the system configuration file
- <c>sys.config</c> is mandatory.</p>
- <p>The installation of a new release may restart the system. Which
- program to use is specified by the SASL configuration
- parameter <c>start_prg</c> which defaults
+ started as an embedded system. Read about this in
+ <seealso marker="doc/embedded:users_guide">Embedded System</seealso> in
+ <em>System Documentation</em>. In this case, the system
+ configuration file <c>sys.config</c> is mandatory.</p>
+ <p>The installation of a new release can restart the system. Which
+ program to use is specified by the <c>SASL</c> configuration
+ parameter <c>start_prg</c>, which defaults
to <c>$ROOT/bin/start</c>.</p>
<p>The emulator restart on Windows NT expects that the system is
started using the <c>erlsrv</c> program (as a service).
- Furthermore the release handler expects that the service is named
- <em>NodeName</em>_<em>Release</em>, where <em>NodeName</em> is
- the first part of the Erlang nodename (up to, but not including
- the "@") and <em>Release</em> is the current version of
- the release. The release handler furthermore expects that a
+ Furthermore, the release handler expects that the service is named
+ <c>NodeName</c>_<c>Release</c>, where <c>NodeName</c> is
+ the first part of the Erlang node name (up to, but not including
+ the "@") and <c>Release</c> is the current release version.
+ The release handler furthermore expects that a
program like <c>start_erl.exe</c> is specified as "machine" to
- <c>erlsrv</c>. During upgrading with restart, a new service will
- be registered and started. The new service will be set to
- automatic and the old service removed as soon as the new release
+ <c>erlsrv</c>. During upgrading with restart, a new service
+ is registered and started. The new service is set to
+ automatic and the old service is removed when the new release
is made permanent.</p>
- <p>The release handler at a node which runs on a diskless machine,
+ <p>The release handler at a node running on a diskless machine,
or with a read-only file system, must be configured accordingly
- using the following <c>sasl</c> configuration parameters (see
- <seealso marker="sasl_app">sasl(6)</seealso> for details):</p>
+ using the following <c>SASL</c> configuration parameters (for
+ details, see <seealso marker="sasl_app">sasl(6)</seealso>):</p>
<taglist>
<tag><c>masters</c></tag>
<item>
- <p>This node uses a number of master nodes in order to store
- and fetch release information. All master nodes must be up
- and running whenever release information is written by this
+ <p>This node uses some master nodes to store
+ and fetch release information. All master nodes must be
+ operational whenever release information is written by this
node.</p>
</item>
<tag><c>client_directory</c></tag>
@@ -145,24 +151,25 @@ old reboot_old permanent
<item>
<p>This parameter specifies if the Erlang emulator is
statically installed at the client node. A node with a static
- emulator cannot dynamically switch to a new emulator because
+ emulator cannot dynamically switch to a new emulator, as
the executable files are statically written into memory.</p>
</item>
</taglist>
- <p>It is also possible to use the release handler to unpack and
+ <p>The release handler can also be used to unpack and
install release packages when not running Erlang as an embedded
- system, but in this case the user must somehow make sure that
+ system. However, in this case the user must somehow ensure that
correct boot scripts and configuration files are used if
- the system needs to be restarted.</p>
- <p>There are additional functions for using another file structure
+ the system must be restarted.</p>
+ <p>Functions are provided for using another file structure
than the structure defined in OTP. These functions can be used
to test a release upgrade locally.</p>
</description>
+
<funcs>
<func>
<name>check_install_release(Vsn) -> {ok, OtherVsn, Descr} | {error, Reason}</name>
<name>check_install_release(Vsn,Opts) -> {ok, OtherVsn, Descr} | {error, Reason}</name>
- <fsummary>Check installation of a release in the system.</fsummary>
+ <fsummary>Checks installation of a release in the system.</fsummary>
<type>
<v>Vsn = OtherVsn = string()</v>
<v>Opts = [Opt]</v>
@@ -173,27 +180,29 @@ old reboot_old permanent
<desc>
<p>Checks if the specified version <c>Vsn</c> of the release
can be installed. The release must not have status
- <c>current</c>. Issues warnings if <c>relup</c> or
- <c>sys.config</c> are not present. If <c>relup</c> is present,
+ <c>current</c>. Issues warnings if <c>relup</c> file or
+ <c>sys.config</c> is not present. If <c>relup</c> file is present,
its contents are checked and <c>{error,Reason}</c> is
returned if an error is found. Also checks that all required
- applications are present and that all new code can be loaded,
- or <c>{error,Reason}</c> is returned.</p>
- <p>This function evaluates all instructions that occur before
+ applications are present and that all new code can be loaded;
+ <c>{error,Reason}</c> is returned if an error is found.</p>
+ <p>Evaluates all instructions that occur before
the <c>point_of_no_return</c> instruction in the release
upgrade script.</p>
- <p>Returns the same as <c>install_release/1</c>. <c>Descr</c>
- defaults to "" if no <c>relup</c> file is found.</p>
- <p>If the option <c>purge</c> is given, all old code that can
- be soft purged will be purged after all other checks are
- successfully completed. This can be useful in order to
+ <p>Returns the same as
+ <seealso marker="#install_release/1"><c>install_release/1</c></seealso>.
+ <c>Descr</c> defaults to "" if no <c>relup</c> file is found.</p>
+ <p>If option <c>purge</c> is specified, all old code that can
+ be soft-purged is purged after all other checks are
+ successfully completed. This can be useful to
reduce the time needed by <seealso
- marker="#install_release/1">install_release</seealso>.</p>
+ marker="#install_release/1"><c>install_release/1</c></seealso>.</p>
</desc>
</func>
+
<func>
<name>create_RELEASES(Root, RelDir, RelFile, AppDirs) -> ok | {error, Reason}</name>
- <fsummary>Create an initial RELEASES file.</fsummary>
+ <fsummary>Creates an initial <c>RELEASES</c> file.</fsummary>
<type>
<v>Root = RelDir = RelFile = string()</v>
<v>AppDirs = [{App, Vsn, Dir}]</v>
@@ -202,52 +211,55 @@ old reboot_old permanent
<v>Reason = term()</v>
</type>
<desc>
- <p>Creates an initial RELEASES file to be used by the release
- handler. This file must exist in order to install new
+ <p>Creates an initial <c>RELEASES</c> file to be used by the
+ release handler. This file must exist to install new
releases.</p>
<p><c>Root</c> is the root of the installation (<c>$ROOT</c>) as
- described above. <c>RelDir</c> is the the directory where
- the <c>RELEASES</c> file should be created (normally
+ described earlier. <c>RelDir</c> is the directory where
+ the <c>RELEASES</c> file is to be created (normally
<c>$ROOT/releases</c>). <c>RelFile</c> is the name
of the <c>.rel</c> file that describes the initial release,
including the extension <c>.rel</c>.</p>
<p><c>AppDirs</c> can be used to specify from where the modules
- for the specified applications should be loaded. <c>App</c> is
+ for the specified applications are to be loaded. <c>App</c> is
the name of an application, <c>Vsn</c> is the version, and
<c>Dir</c> is the name of the directory where <c>App-Vsn</c>
- is located. The corresponding modules should be located under
+ is located. The corresponding modules are to be located under
<c>Dir/App-Vsn/ebin</c>. The directories for applications not
specified in <c>AppDirs</c> are assumed to be located in
<c>$ROOT/lib</c>.</p>
</desc>
</func>
+
<func>
<name>install_file(Vsn, File) -> ok | {error, Reason}</name>
- <fsummary>Install a release file in the release structure.</fsummary>
+ <fsummary>Installs a release file in the release structure.</fsummary>
<type>
<v>Vsn = File = string()</v>
<v>Reason = term()</v>
</type>
<desc>
- <p>Installs a release dependent file in the release structure.
- A release dependent file is a file that must be in
+ <p>Installs a release-dependent file in the release structure.
+ The release-dependent file must be in
the release structure when a new release is installed:
- <c>start.boot</c>, <c>relup</c> and <c>sys.config</c>.</p>
+ <c>start.boot</c>, <c>relup</c>, and <c>sys.config</c>.</p>
<p>The function can be called, for example, when these files
- are generated at the target. It should be called after
- <c>set_unpacked/2</c> has been called.</p>
+ are generated at the target. The function is to be called after
+ <seealso marker="#set_unpacked/2"><c>set_unpacked/2</c></seealso>
+ has been called.</p>
</desc>
</func>
+
<func>
<name>install_release(Vsn) -> {ok, OtherVsn, Descr} | {error, Reason}</name>
<name>install_release(Vsn, [Opt]) -> {ok, OtherVsn, Descr} | {continue_after_restart, OtherVsn, Descr} | {error, Reason}</name>
- <fsummary>Install a release in the system.</fsummary>
+ <fsummary>Installs a release in the system.</fsummary>
<type>
<v>Vsn = OtherVsn = string()</v>
<v>Opt = {error_action, Action} | {code_change_timeout, Timeout}</v>
<v>&nbsp;&nbsp;&nbsp;| {suspend_timeout, Timeout} | {update_paths, Bool}</v>
<v>&nbsp;Action = restart | reboot</v>
- <v>&nbsp;Timeout = default | infinity | int()>0</v>
+ <v>&nbsp;Timeout = default | infinity | pos_integer()</v>
<v>&nbsp;Bool = boolean()</v>
<v>Descr = term()</v>
<v>Reason = {illegal_option, Opt} | {already_installed, Vsn} | {change_appl_data, term()} | {missing_base_app, OtherVsn, App} | {could_not_create_hybrid_boot, term()} | term()</v>
@@ -262,7 +274,7 @@ old reboot_old permanent
version and a script <c>{Vsn,Descr2,Instructions2}</c> in this
file for downgrading to <c>Vsn</c>.</p>
<p>If a script is found, the first thing that happens is that
- the applications specifications are updated according to
+ the application specifications are updated according to
the <c>.app</c> files and <c>sys.config</c> belonging to
the release version <c>Vsn</c>.</p>
<p>After the application specifications have been updated,
@@ -271,101 +283,120 @@ old reboot_old permanent
<c>OtherVsn</c> and <c>Descr</c> are the version
(<c>UpFromVsn</c> or <c>Vsn</c>) and description
(<c>Descr1</c> or <c>Descr2</c>) as specified in the script.</p>
- <p>If <c>{continue_after_restart,OtherVsn,Descr}</c> is
- returned, it means that the emulator will be restarted
- before the upgrade instructions are executed. This will
- happen if the emulator or any of the applications kernel,
- stdlib or sasl are updated. The new version of the emulator
- and these core applications will execute after the restart,
- but for all other applications the old versions will be
- started and the upgrade will be performed as normal by
+ <p>If <c>{continue_after_restart,OtherVsn,Descr}</c> is
+ returned, the emulator is restarted
+ before the upgrade instructions are executed. This
+ occurs if the emulator or any of the applications
+ <c>Kernel</c>, <c>STDLIB</c>, or <c>SASL</c>
+ are updated. The new emulator version
+ and these core applications execute after the restart.
+ For all other applications the old versions are
+ started and the upgrade is performed as normal by
executing the upgrade instructions.</p>
<p>If a recoverable error occurs, the function returns
<c>{error,Reason}</c> and the original application
specifications are restored. If a non-recoverable error
occurs, the system is restarted.</p>
- <p>The option <c>error_action</c> defines if the node should be
- restarted (<c>init:restart()</c>) or rebooted
- (<c>init:reboot()</c>) in case of an error during
- the installation. Default is <c>restart</c>.</p>
- <p>The option <c>code_change_timeout</c> defines the timeout
- for all calls to <c>sys:change_code</c>. If no value is
- specified or <c>default</c> is given, the default value
- defined in <c>sys</c> is used.</p>
- <p>The option <c>suspend_timeout</c> defines the timeout for
- all calls to <c>sys:suspend</c>. If no value is specified,
- the values defined by the <c>Timeout</c> parameter of
- the <c>upgrade</c> or <c>suspend</c> instructions are used.
- If <c>default</c> is specified, the default value defined in
- <c>sys</c> is used.</p>
- <p>The option <c>{update_paths,Bool}</c> indicates if all
- application code paths should be updated (<c>Bool==true</c>),
- or if only code paths for modified applications should be
- updated (<c>Bool==false</c>, default). This option only has
- effect for other application directories than the default
- <c>$ROOT/lib/App-Vsn</c>, that is, application directories
- provided in the <c>AppDirs</c> argument in a call to
- <c>create_RELEASES/4</c> or <c>set_unpacked/2</c>.</p>
- <p>Example: In the current version <c>CurVsn</c> of a release,
- the application directory of <c>myapp</c> is
- <c>$ROOT/lib/myapp-1.0</c>. A new version <c>NewVsn</c> is
- unpacked outside the release handler, and the release handler
- is informed about this with a call to:</p>
- <code type="none">
+ <p><em>Options</em>:</p>
+ <taglist>
+ <tag><c>error_action</c></tag>
+ <item><p>Defines if the node is to be
+ restarted
+ (<seealso marker="erts:init#restart/0"><c>init:restart()</c></seealso>)
+ or rebooted
+ (<seealso marker="erts:init#reboot/0"><c>init:reboot()</c></seealso>)
+ if there is an error during
+ the installation. Default is <c>restart</c>.</p></item>
+ <tag><c>code_change_timeout</c></tag>
+ <item><p>Defines the time-out
+ for all calls to
+ <seealso marker="stdlib:sys#change_code/4"><c>stdlib:sys:change_code</c></seealso>.
+ If no value is specified or <c>default</c> is specified, the
+ default value defined in <c>sys</c> is used.</p></item>
+ <tag><c>suspend_timeout</c></tag>
+ <item><p>Defines the time-out for
+ all calls to
+ <seealso marker="stdlib:sys#suspend/1"><c>stdlib:sys:suspend</c></seealso>.
+ If no value is specified, the values defined by the <c>Timeout</c>
+ parameter of the <c>upgrade</c> or <c>suspend</c> instructions are used.
+ If <c>default</c> is specified, the default value defined in
+ <c>sys</c> is used.</p></item>
+ <tag><c>{update_paths,Bool}</c></tag>
+ <item><p>Indicates if all
+ application code paths are to be updated (<c>Bool==true</c>)
+ or if only code paths for modified applications are to be
+ updated (<c>Bool==false</c>, default). This option has only
+ effect for other application directories than the default
+ <c>$ROOT/lib/App-Vsn</c>, that is, application directories
+ specified in argument <c>AppDirs</c> in a call to
+ <seealso marker="#create_RELEASES/4"><c>create_RELEASES/4</c></seealso> or
+ <seealso marker="#set_unpacked/2"><c>set_unpacked/2</c></seealso>.</p>
+ <p><em>Example:</em></p>
+ <p>In the current version <c>CurVsn</c> of a release, the
+ application directory of <c>myapp</c> is
+ <c>$ROOT/lib/myapp-1.0</c>. A new version <c>NewVsn</c> is
+ unpacked outside the release handler and the release
+ handler is informed about this with a call as follows:</p>
+ <code type="none">
release_handler:set_unpacked(RelFile, [{myapp,"1.0","/home/user"},...]).
-=> {ok,NewVsn}
- </code>
- <p>If <c>NewVsn</c> is installed with the option
- <c>{update_paths,true}</c>, afterwards
- <c>code:lib_dir(myapp)</c> will return
- <c>/home/user/myapp-1.0</c>.</p>
+=> {ok,NewVsn}</code>
+ <p>If <c>NewVsn</c> is installed with option
+ <c>{update_paths,true}</c>, then
+ <seealso marker="kernel:code#lib_dir/1"><c>kernel:code:lib_dir(myapp)</c></seealso>
+ returns <c>/home/user/myapp-1.0</c>.</p></item>
+ </taglist>
<note>
- <p>Installing a new release might be quite time consuming if
+ <p>Installing a new release can be time consuming if
there are many processes in the system. The reason is that
each process must be checked for references to old code
- before a module can be purged. This check might lead to
+ before a module can be purged. This check can lead to
garbage collections and copying of data.</p>
- <p>If you wish to speed up the execution of
- <c>install_release</c>, then you may call <seealso
- marker="#check_install_release/1">check_install_release</seealso>
- first, using the option <c>purge</c>. This will do the same
- check for old code, and then purge all modules that can be
- soft purged. The purged modules will then no longer have any
- old code, and <c>install_release</c> will not need to do the
+ <p>To speed up the execution of
+ <seealso marker="#install_release/1"><c>install_release</c></seealso>,
+ first call <seealso
+ marker="#check_install_release/1"><c>check_install_release</c></seealso>,
+ using option <c>purge</c>. This does the same
+ check for old code. Then purges all modules that can be
+ soft-purged. The purged modules do then no longer have any
+ old code, and
+ <seealso marker="#install_release/1"><c>install_release</c></seealso>
+ does not need to do the
checks.</p>
- <p>Obviously, this will not reduce the overall time for the
- upgrade, but it will allow checks and purge to be executed
+ <p>This does not reduce the overall time for the
+ upgrade, but it allows checks and purge to be executed
in the background before the real upgrade is started.</p>
</note>
<note>
<p>When upgrading the emulator from a version older than OTP
- R15, there will be an attempt to load new application beam
- code into the old emulator. In some cases, the new beam
- format can not be read by the old emulator, and so the code
- loading will fail and terminate the complete upgrade. To
- overcome this problem, the new application code should be
- compiled with the old emulator. See <seealso
- marker="doc/design_principles:appup_cookbook">Design
- Principles</seealso> for more information about emulator
- upgrade from pre OTP R15 versions.</p>
+ R15, an attempt is made to load new application beam
+ code into the old emulator. Sometimes the new beam
+ format cannot be read by the old emulator, so the code
+ loading fails and the complete upgrade is terminated. To
+ overcome this problem, the new application code is to be
+ compiled with the old emulator. For more information about
+ emulator upgrade from pre OTP R15 versions, see
+ <seealso marker="doc/design_principles:appup_cookbook">Design
+ Principles</seealso> in <em>System Documentation</em>.</p>
</note>
</desc>
</func>
+
<func>
<name>make_permanent(Vsn) -> ok | {error, Reason}</name>
- <fsummary>Make the specified release version permanent.</fsummary>
+ <fsummary>Makes the specified release version permanent.</fsummary>
<type>
<v>Vsn = string()</v>
<v>Reason = {bad_status, Status} | term()</v>
</type>
<desc>
- <p>Makes the specified version <c>Vsn</c> of the release
+ <p>Makes the specified release version <c>Vsn</c>
permanent.</p>
</desc>
</func>
+
<func>
<name>remove_release(Vsn) -> ok | {error, Reason}</name>
- <fsummary>Remove a release from the system.</fsummary>
+ <fsummary>Removes a release from the system.</fsummary>
<type>
<v>Vsn = string()</v>
<v>Reason = {permanent, Vsn} | client_node | term()</v>
@@ -375,23 +406,26 @@ release_handler:set_unpacked(RelFile, [{myapp,"1.0","/home/user"},...]).
The release must not be the permanent release. Removes only
the files and directories not in use by another release.</p>
</desc>
+
</func>
<func>
<name>reboot_old_release(Vsn) -> ok | {error, Reason}</name>
- <fsummary>Reboot the system from an old release.</fsummary>
+ <fsummary>Reboots the system from an old release.</fsummary>
<type>
<v>Vsn = string()</v>
<v>Reason = {bad_status, Status} | term()</v>
</type>
<desc>
<p>Reboots the system by making the old release permanent, and
- calls <c>init:reboot()</c> directly. The release must have
- status <c>old</c>.</p>
+ calls
+ <seealso marker="erts:init#reboot/0"><c>init:reboot()</c></seealso>
+ directly. The release must have status <c>old</c>.</p>
</desc>
</func>
+
<func>
<name>set_removed(Vsn) -> ok | {error, Reason}</name>
- <fsummary>Mark a release as removed.</fsummary>
+ <fsummary>Marks a release as removed.</fsummary>
<type>
<v>Vsn = string()</v>
<v>Reason = {permanent, Vsn} | term()</v>
@@ -403,9 +437,10 @@ release_handler:set_unpacked(RelFile, [{myapp,"1.0","/home/user"},...]).
not delete any files.</p>
</desc>
</func>
+
<func>
<name>set_unpacked(RelFile, AppDirs) -> {ok, Vsn} | {error, Reason}</name>
- <fsummary>Mark a release as unpacked.</fsummary>
+ <fsummary>Marks a release as unpacked.</fsummary>
<type>
<v>RelFile = string()</v>
<v>AppDirs = [{App, Vsn, Dir}]</v>
@@ -419,18 +454,19 @@ release_handler:set_unpacked(RelFile, [{myapp,"1.0","/home/user"},...]).
the release is unpacked. <c>Vsn</c> is extracted from
the release resource file <c>RelFile</c>.</p>
<p><c>AppDirs</c> can be used to specify from where the modules
- for the specified applications should be loaded. <c>App</c> is
+ for the specified applications are to be loaded. <c>App</c> is
the name of an application, <c>Vsn</c> is the version, and
<c>Dir</c> is the name of the directory where <c>App-Vsn</c>
- is located. The corresponding modules should be located under
+ is located. The corresponding modules are to be located under
<c>Dir/App-Vsn/ebin</c>. The directories for applications not
specified in <c>AppDirs</c> are assumed to be located in
<c>$ROOT/lib</c>.</p>
</desc>
</func>
+
<func>
<name>unpack_release(Name) -> {ok, Vsn} | {error, Reason}</name>
- <fsummary>Unpack a release package.</fsummary>
+ <fsummary>Unpacks a release package.</fsummary>
<type>
<v>Name = Vsn = string()</v>
<v>Reason = client_node | term()</v>
@@ -438,14 +474,15 @@ release_handler:set_unpacked(RelFile, [{myapp,"1.0","/home/user"},...]).
<desc>
<p>Unpacks a release package <c>Name.tar.gz</c> located in
the <c>releases</c> directory.</p>
- <p>Performs some checks on the package - for example checks
- that all mandatory files are present - and extracts its
+ <p>Performs some checks on the package, for example, checks
+ that all mandatory files are present, and extracts its
contents.</p>
</desc>
</func>
+
<func>
<name>which_releases() -> [{Name, Vsn, Apps, Status}]</name>
- <fsummary>Return all known releases</fsummary>
+ <fsummary>Returns all known releases.</fsummary>
<type>
<v>Name = Vsn = string()</v>
<v>Apps = ["App-Vsn"]</v>
@@ -455,16 +492,18 @@ release_handler:set_unpacked(RelFile, [{myapp,"1.0","/home/user"},...]).
<p>Returns all releases known to the release handler.</p>
</desc>
</func>
+
<func>
<name>which_releases(Status) -> [{Name, Vsn, Apps, Status}]</name>
- <fsummary>Return all known releases of a specific status</fsummary>
+ <fsummary>Returns all known releases of a specific status.</fsummary>
<type>
<v>Name = Vsn = string()</v>
<v>Apps = ["App-Vsn"]</v>
<v>Status = unpacked | current | permanent | old</v>
</type>
<desc>
- <p>Returns all releases known to the release handler of a specific status.</p>
+ <p>Returns all releases, known to the release handler, of a
+ specific status.</p>
</desc>
</func>
</funcs>
@@ -473,7 +512,8 @@ release_handler:set_unpacked(RelFile, [{myapp,"1.0","/home/user"},...]).
<title>Application Upgrade/Downgrade</title>
<p>The following functions can be used to test upgrade and downgrade
of single applications (instead of upgrading/downgrading an entire
- release). A script corresponding to <c>relup</c> is created
+ release). A script corresponding to the instructions in the
+ <c>relup</c> file is created
on-the-fly, based on the <c>.appup</c> file for the application,
and evaluated exactly in the same way as <c>release_handler</c>
does.</p>
@@ -482,20 +522,22 @@ release_handler:set_unpacked(RelFile, [{myapp,"1.0","/home/user"},...]).
of <c>.appup</c> files. They are not run within the context of
the <c>release_handler</c> process. They must therefore
<em>not</em> be used together with calls to
- <c>install_release/1,2</c>, as this will cause
+ <seealso marker="#install_release/1"><c>install_release/1,2</c></seealso>,
+ as this causes the
<c>release_handler</c> to end up in an inconsistent state.</p>
- <p>No persistent information is updated, why these functions can
+ <p>No persistent information is updated, so these functions can
be used on any Erlang node, embedded or not. Also, using these
- functions does not affect which code will be loaded in case of
+ functions does not affect which code is loaded if there is
a reboot.</p>
- <p>If the upgrade or downgrade fails, the application may end up
+ <p>If the upgrade or downgrade fails, the application can end up
in an inconsistent state.</p>
</warning>
</section>
+
<funcs>
<func>
<name>upgrade_app(App, Dir) -> {ok, Unpurged} | restart_emulator | {error, Reason}</name>
- <fsummary>Upgrade to a new application version</fsummary>
+ <fsummary>Upgrades to a new application version.</fsummary>
<type>
<v>App = atom()</v>
<v>Dir = string()</v>
@@ -506,39 +548,46 @@ release_handler:set_unpacked(RelFile, [{myapp,"1.0","/home/user"},...]).
<desc>
<p>Upgrades an application <c>App</c> from the current
version to a new version located in <c>Dir</c> according to
- the <c>.appup</c> script.</p>
+ the <c>.appup</c> file.</p>
<p><c>App</c> is the name of the application, which must be
started. <c>Dir</c> is the new library directory of
- <c>App</c>, the corresponding modules as well as
- the <c>.app</c> and <c>.appup</c> files should be located
+ <c>App</c>. The corresponding modules as well as
+ the <c>.app</c> and <c>.appup</c> files are to be located
under <c>Dir/ebin</c>.</p>
<p>The function looks in the <c>.appup</c> file and tries to
find an upgrade script from the current version of
the application using
- <seealso marker="#upgrade_script/2">upgrade_script/2</seealso>.
+ <seealso marker="#upgrade_script/2"><c>upgrade_script/2</c></seealso>.
This script is evaluated using
- <seealso marker="#eval_appup_script/4">eval_appup_script/4</seealso>,
+ <seealso marker="#eval_appup_script/4"><c>eval_appup_script/4</c></seealso>,
exactly in the same way as
- <seealso marker="#install_release/1">install_release/1,2</seealso>
+ <seealso marker="#install_release/1"><c>install_release/1,2</c></seealso>
does.</p>
- <p>Returns <c>{ok, Unpurged}</c> if evaluating the script is
- successful, where <c>Unpurged</c> is a list of unpurged
- modules, or <c>restart_emulator</c> if this instruction is
- encountered in the script, or <c>{error, Reason}</c> if
- an error occurred when finding or evaluating the script.</p>
+ <p>Returns one of the following:</p>
+ <list type="bulleted">
+ <item><c>{ok, Unpurged}</c> if evaluating the script is
+ successful, where <c>Unpurged</c> is a list of unpurged
+ modules</item>
+ <item><c>restart_emulator</c> if this instruction is
+ encountered in the script</item>
+ <item><c>{error, Reason}</c> if an error occurred when
+ finding or evaluating the script</item>
+ </list>
<p>If the <c>restart_new_emulator</c> instruction is found in
- the script, <c>upgrade_app/2</c> will return
- <c>{error,restart_new_emulator}</c>. The reason for this is
- that this instruction requires that a new version of the
- emulator is started before the rest of the upgrade
- instructions can be executed, and this can only be done by
- <c>install_release/1,2</c>.</p>
+ the script,
+ <seealso marker="#upgrade_app/2"><c>upgrade_app/2</c></seealso>
+ returns <c>{error,restart_new_emulator}</c>. This because
+ <c>restart_new_emulator</c> requires a new version of the
+ emulator to be started before the rest of the upgrade
+ instructions can be executed, and this can only be done by
+ <seealso marker="#install_release/1"><c>install_release/1,2</c></seealso>.</p>
</desc>
</func>
+
<func>
<name>downgrade_app(App, Dir) -></name>
<name>downgrade_app(App, OldVsn, Dir) -> {ok, Unpurged} | restart_emulator | {error, Reason}</name>
- <fsummary>Downgrade to a previous application version</fsummary>
+ <fsummary>Downgrades to a previous application version.</fsummary>
<type>
<v>App = atom()</v>
<v>Dir = OldVsn = string()</v>
@@ -549,110 +598,124 @@ release_handler:set_unpacked(RelFile, [{myapp,"1.0","/home/user"},...]).
<desc>
<p>Downgrades an application <c>App</c> from the current
version to a previous version <c>OldVsn</c> located in
- <c>Dir</c> according to the <c>.appup</c> script.</p>
+ <c>Dir</c> according to the <c>.appup</c> file.</p>
<p><c>App</c> is the name of the application, which must be
- started. <c>OldVsn</c> is the previous version of
- the application and can be omitted if <c>Dir</c> is of
+ started. <c>OldVsn</c> is the previous application version
+ and can be omitted if <c>Dir</c> is of
the format <c>"App-OldVsn"</c>. <c>Dir</c> is the library
- directory of this previous version of <c>App</c>,
- the corresponding modules as well as the old <c>.app</c> file
- should be located under <c>Dir/ebin</c>. The <c>.appup</c>
- file should be located in the <c>ebin</c> directory of
+ directory of the previous version of <c>App</c>.
+ The corresponding modules and the old <c>.app</c> file
+ are to be located under <c>Dir/ebin</c>. The <c>.appup</c>
+ file is to be located in the <c>ebin</c> directory of
the <em>current</em> library directory of the application
- (<c>code:lib_dir(App)</c>).</p>
+ (<seealso marker="kernel:code#lib_dir/1"><c>code:lib_dir(App)</c></seealso>).</p>
<p>The function looks in the <c>.appup</c> file and tries to
- find an downgrade script to the previous version of
+ find a downgrade script to the previous version of
the application using
- <seealso marker="#downgrade_script/3">downgrade_script/3</seealso>.
+ <seealso marker="#downgrade_script/3"><c>downgrade_script/3</c></seealso>.
This script is evaluated using
- <seealso marker="#eval_appup_script/4">eval_appup_script/4</seealso>,
+ <seealso marker="#eval_appup_script/4"><c>eval_appup_script/4</c></seealso>,
exactly in the same way as
- <seealso marker="#install_release/1">install_release/1,2</seealso>
+ <seealso marker="#install_release/1"><c>install_release/1,2</c></seealso>
does.</p>
- <p>Returns <c>{ok, Unpurged}</c> if evaluating the script is
- successful, where <c>Unpurged</c> is a list of unpurged
- modules, or <c>restart_emulator</c> if this instruction is
- encountered in the script, or <c>{error, Reason}</c> if
- an error occurred when finding or evaluating the script.</p>
+ <p>Returns one of the following:</p>
+ <list type="bulleted">
+ <item><c>{ok, Unpurged}</c> if evaluating the script is
+ successful, where <c>Unpurged</c> is a list of unpurged
+ modules</item>
+ <item><c>restart_emulator</c> if this instruction is
+ encountered in the script</item>
+ <item><c>{error, Reason}</c> if an error occurred when
+ finding or evaluating the script</item>
+ </list>
</desc>
</func>
+
<func>
<name>upgrade_script(App, Dir) -> {ok, NewVsn, Script}</name>
- <fsummary>Find an application upgrade script</fsummary>
+ <fsummary>Finds an application upgrade script.</fsummary>
<type>
<v>App = atom()</v>
<v>Dir = string()</v>
<v>NewVsn = string()</v>
- <v>Script = Instructions -- see appup(4)</v>
+ <v>Script = Instructions</v>
</type>
<desc>
<p>Tries to find an application upgrade script for <c>App</c>
from the current version to a new version located in
<c>Dir</c>.</p>
<p>The upgrade script can then be evaluated using
- <seealso marker="#eval_appup_script/4">eval_appup_script/4</seealso>.
+ <seealso marker="#eval_appup_script/4"><c>eval_appup_script/4</c></seealso>.
It is recommended to use
- <seealso marker="#upgrade_app/2">upgrade_app/2</seealso>
- instead, but this function is useful in order to inspect
- the contents of the script.</p>
+ <seealso marker="#upgrade_app/2"><c>upgrade_app/2</c></seealso>
+ instead, but this function (<c>upgrade_script</c>) is useful
+ to inspect the contents of the script.</p>
<p><c>App</c> is the name of the application, which must be
started. <c>Dir</c> is the new library directory of
- <c>App</c>, the corresponding modules as well as
- the <c>.app</c> and <c>.appup</c> files should be located
+ <c>App</c>. The corresponding modules as well as
+ the <c>.app</c> and <c>.appup</c> files are to be located
under <c>Dir/ebin</c>.</p>
<p>The function looks in the <c>.appup</c> file and tries to
- find an upgrade script from the current version of
- the application. High-level instructions are translated to
- low-level instructions and the instructions are sorted in
- the same manner as when generating a <c>relup</c> script.</p>
+ find an upgrade script from the current application version.
+ High-level instructions are translated to
+ low-level instructions. The instructions are sorted in
+ the same manner as when generating a <c>relup</c> file.</p>
<p>Returns <c>{ok, NewVsn, Script}</c> if successful, where
- <c>NewVsn</c> is the new application version.</p>
+ <c>NewVsn</c> is the new application version.
+ For details about <c>Script</c>, see
+ <seealso marker="appup"><c>appup(4)</c></seealso>.</p>
<p>Failure: If a script cannot be found, the function fails
with an appropriate error reason.</p>
</desc>
</func>
+
<func>
<name>downgrade_script(App, OldVsn, Dir) -> {ok, Script}</name>
- <fsummary>Find an application downgrade script</fsummary>
+ <fsummary>Finds an application downgrade script.</fsummary>
<type>
<v>App = atom()</v>
<v>OldVsn = Dir = string()</v>
- <v>Script = Instructions -- see appup(4)</v>
+ <v>Script = Instructions</v>
</type>
<desc>
<p>Tries to find an application downgrade script for <c>App</c>
from the current version to a previous version <c>OldVsn</c>
located in <c>Dir</c>.</p>
<p>The downgrade script can then be evaluated using
- <seealso marker="#eval_appup_script/4">eval_appup_script/4</seealso>.
+ <seealso marker="#eval_appup_script/4"><c>eval_appup_script/4</c></seealso>.
It is recommended to use
- <seealso marker="#downgrade_app/2">downgrade_app/2,3</seealso>
- instead, but this function is useful in order to inspect
- the contents of the script.</p>
+ <seealso marker="#downgrade_app/2"><c>downgrade_app/2,3</c></seealso>
+ instead, but this function (<c>downgrade_script</c>) is useful
+ to inspect the contents of the script.</p>
<p><c>App</c> is the name of the application, which must be
started. <c>Dir</c> is the previous library directory of
- <c>App</c>, the corresponding modules as well as
- the old <c>.app</c> file should be located under
- <c>Dir/ebin</c>. The <c>.appup</c> file should be located in
+ <c>App</c>. The corresponding modules and
+ the old <c>.app</c> file are to be located under
+ <c>Dir/ebin</c>. The <c>.appup</c> file is to be located in
the <c>ebin</c> directory of the <em>current</em> library
- directory of the application (<c>code:lib_dir(App)</c>).</p>
+ directory of the application
+ (<seealso marker="kernel:code#lib_dir/1"><c>code:lib_dir(App)</c>)</seealso>.</p>
<p>The function looks in the <c>.appup</c> file and tries to
- find an downgrade script from the current version of
- the application. High-level instructions are translated to
- low-level instructions and the instructions are sorted in
- the same manner as when generating a <c>relup</c> script.</p>
- <p>Returns <c>{ok, Script}</c> if successful.</p>
+ find a downgrade script from the current application version.
+ High-level instructions are translated to
+ low-level instructions. The instructions are sorted in
+ the same manner as when generating a <c>relup</c> file.</p>
+ <p>Returns <c>{ok, Script}</c> if successful.
+ For details about <c>Script</c>, see
+ <seealso marker="appup"><c>appup(4)</c></seealso>.</p>
<p>Failure: If a script cannot be found, the function fails
with an appropriate error reason.</p>
</desc>
</func>
+
<func>
<name>eval_appup_script(App, ToVsn, ToDir, Script) -> {ok, Unpurged} | restart_emulator | {error, Reason}</name>
- <fsummary>Evaluate an application upgrade or downgrade script</fsummary>
+ <fsummary>Evaluates an application upgrade or downgrade script.</fsummary>
<type>
<v>App = atom()</v>
<v>ToVsn = ToDir = string()</v>
- <v>Script -- see upgrade_script/2, downgrade_script/3</v>
+ <v>Script</v>
+ <d>See <seealso marker="#upgrade_script/2"><c>upgrade_script/2</c></seealso>, <seealso marker="#downgrade_script/3"><c>downgrade_script/3</c></seealso></d>
<v>Unpurged = [Module]</v>
<v>&nbsp;Module = atom()</v>
<v>Reason = term()</v>
@@ -660,114 +723,100 @@ release_handler:set_unpacked(RelFile, [{myapp,"1.0","/home/user"},...]).
<desc>
<p>Evaluates an application upgrade or downgrade script
<c>Script</c>, the result from calling
- <seealso marker="#upgrade_app/2">upgrade_script/2</seealso> or
- <seealso marker="#downgrade_app/3">downgrade_script/3</seealso>,
+ <seealso marker="#upgrade_script/2"><c>upgrade_script/2</c></seealso> or
+ <seealso marker="#downgrade_script/3"><c>downgrade_script/3</c></seealso>,
exactly in the same way as
- <seealso marker="#install_release/1">install_release/1,2</seealso>
+ <seealso marker="#install_release/1"><c>install_release/1,2</c></seealso>
does.</p>
<p><c>App</c> is the name of the application, which must be
started. <c>ToVsn</c> is the version to be upgraded/downgraded
to, and <c>ToDir</c> is the library directory of this version.
The corresponding modules as well as the <c>.app</c> and
- <c>.appup</c> files should be located under <c>Dir/ebin</c>.</p>
- <p>Returns <c>{ok, Unpurged}</c> if evaluating the script is
- successful, where <c>Unpurged</c> is a list of unpurged
- modules, or <c>restart_emulator</c> if this instruction is
- encountered in the script, or <c>{error, Reason}</c> if
- an error occurred when evaluating the script.</p>
- <p>If the <c>restart_new_emulator</c> instruction is found in
- the script, <c>eval_appup_script/4</c> will return
- <c>{error,restart_new_emulator}</c>. The reason for this is
- that this instruction requires that a new version of the
- emulator is started before the rest of the upgrade
- instructions can be executed, and this can only be done by
- <c>install_release/1,2</c>.</p>
+ <c>.appup</c> files are to be located under <c>Dir/ebin</c>.</p>
+ <p>Returns one of the following:</p>
+ <list type="bulleted">
+ <item><c>{ok, Unpurged}</c> if evaluating the script is
+ successful, where <c>Unpurged</c> is a list of unpurged
+ modules</item>
+ <item><c>restart_emulator</c> if this instruction is
+ encountered in the script</item>
+ <item><c>{error, Reason}</c> if an error occurred when
+ finding or evaluating the script</item>
+ </list>
+ <p>If the <c>restart_new_emulator</c> instruction is found in
+ the script,
+ <seealso marker="#eval_appup_script/4"><c>eval_appup_script/4</c></seealso>
+ returns <c>{error,restart_new_emulator}</c>. This because
+ <c>restart_new_emulator</c> requires a new version of the
+ emulator to be started before the rest of the upgrade
+ instructions can be executed, and this can only be done by
+ <seealso marker="#install_release/1"><c>install_release/1,2</c></seealso>.</p>
</desc>
</func>
</funcs>
<section>
<title>Typical Error Reasons</title>
- <list type="bulleted">
- <item>
- <p><c>{bad_masters, Masters}</c> - The master nodes
- <c>Masters</c> are not alive.</p>
- </item>
- <item>
- <p><c>{bad_rel_file, File}</c> - Specified <c>.rel</c> file
- <c>File</c> can not be read, or does not contain a single
- term.</p>
- </item>
- <item>
- <p><c>{bad_rel_data, Data}</c> - Specified <c>.rel</c> file
- does not contain a recognized release specification, but
- another term <c>Data</c>.</p>
- </item>
- <item>
- <p><c>{bad_relup_file, File}</c> - Specified <c>relup</c> file
- <c>Relup</c> contains bad data.</p>
- </item>
- <item>
- <p><c>{cannot_extract_file, Name, Reason}</c> - Problems when
- extracting from a tar file, <c>erl_tar:extract/2</c> returned
- <c>{error, {Name, Reason}}</c>.</p>
- </item>
- <item>
- <p><c>{existing_release, Vsn}</c> - Specified release version
- <c>Vsn</c> is already in use.</p>
- </item>
- <item>
- <p><c>{Master, Reason, When}</c> - Some operation, indicated by
- the term <c>When</c>, failed on the master node <c>Master</c>
- with the specified error reason <c>Reason</c>.</p>
- </item>
- <item>
- <p><c>{no_matching_relup, Vsn, CurrentVsn}</c> - Cannot find a
- script for up/downgrading between <c>CurrentVsn</c> and
- <c>Vsn</c>.</p>
- </item>
- <item>
- <p><c>{no_such_directory, Path}</c> - The directory <c>Path</c>
- does not exist.</p>
- </item>
- <item>
- <p><c>{no_such_file, Path}</c> - The path <c>Path</c> (file or
- directory) does not exist.</p>
- </item>
- <item>
- <p><c>{no_such_file, {Master, Path}}</c> - The path <c>Path</c>
- (file or directory) does not exist at the master node
- <c>Master</c>.</p>
- </item>
- <item>
- <p><c>{no_such_release, Vsn}</c> - The specified version
- <c>Vsn</c> of the release does not exist.</p>
- </item>
- <item>
- <p><c>{not_a_directory, Path}</c> - <c>Path</c> exists, but is
- not a directory.</p>
- </item>
- <item>
- <p><c>{Posix, File}</c> - Some file operation failed for
- <c>File</c>. <c>Posix</c> is an atom named from the Posix
- error codes, such as <c>enoent</c>, <c>eacces</c> or
- <c>eisdir</c>. See <c>file(3)</c>.</p>
- </item>
- <item>
- <p><c>Posix</c> - Some file operation failed, as above.</p>
- </item>
- </list>
+ <taglist>
+ <tag><c>{bad_masters, Masters}</c></tag>
+ <item><p>The master nodes <c>Masters</c> are not alive.</p></item>
+ <tag><c>{bad_rel_file, File}</c></tag>
+ <item><p>Specified <c>.rel</c> file <c>File</c> cannot be read or
+ does not contain a single term.</p></item>
+ <tag><c>{bad_rel_data, Data}</c></tag>
+ <item><p>Specified <c>.rel</c> file does not contain a recognized
+ release specification, but another term <c>Data</c>.</p></item>
+ <tag><c>{bad_relup_file, File}</c></tag>
+ <item><p>Specified <c>relup</c> file <c>Relup</c> contains bad
+ data.</p></item>
+ <tag><c>{cannot_extract_file, Name, Reason}</c></tag>
+ <item><p>Problems when extracting from a tar file,
+ <seealso marker="stdlib:erl_tar#extract/2"><c>erl_tar:extract/2</c></seealso>
+ returned <c>{error, {Name, Reason}}</c>.</p></item>
+ <tag><c>{existing_release, Vsn}</c></tag>
+ <item><p>Specified release version <c>Vsn</c> is already
+ in use.</p></item>
+ <tag><c>{Master, Reason, When}</c></tag>
+ <item><p>Some operation, indicated by the term <c>When</c>, failed
+ on the master node <c>Master</c> with the specified error
+ reason <c>Reason</c>.</p></item>
+ <tag><c>{no_matching_relup, Vsn, CurrentVsn}</c></tag>
+ <item><p>Cannot find a script for upgrading/downgrading between
+ <c>CurrentVsn</c> and <c>Vsn</c>.</p></item>
+ <tag><c>{no_such_directory, Path}</c></tag>
+ <item><p>The directory <c>Path</c>does not exist.</p></item>
+ <tag><c>{no_such_file, Path}</c></tag>
+ <item><p>The path <c>Path</c> (file or directory) does not
+ exist.</p></item>
+ <tag><c>{no_such_file, {Master, Path}}</c></tag>
+ <item><p>The path <c>Path</c> (file or directory) does not exist at
+ the master node <c>Master</c>.</p></item>
+ <tag><c>{no_such_release, Vsn}</c></tag>
+ <item><p>The specified release version <c>Vsn</c> does not
+ exist.</p></item>
+ <tag><c>{not_a_directory, Path}</c></tag>
+ <item><p><c>Path</c> exists but is not a directory.</p></item>
+ <tag><c>{Posix, File}</c></tag>
+ <item><p>Some file operation failed for <c>File</c>. <c>Posix</c>
+ is an atom named from the Posix error codes, such as
+ <c>enoent</c>, <c>eacces</c>, or <c>eisdir</c>. See
+ <seealso marker="kernel:file"><c>file(3)</c></seealso>
+ in <c>Kernel</c>.</p></item>
+ <tag><c>Posix</c></tag>
+ <item><p>Some file operation failed, as for the previous item in
+ the list.</p></item>
+ </taglist>
</section>
<section>
- <title>SEE ALSO</title>
- <p><seealso marker="doc/design_principles:release_handling">OTP Design Principles</seealso>,
- <seealso marker="kernel:config">config(4)</seealso>,
- <seealso marker="relup">relup(4)</seealso>,
- <seealso marker="rel">rel(4)</seealso>,
- <seealso marker="script">script(4)</seealso>,
- <seealso marker="stdlib:sys">sys(3)</seealso>,
- <seealso marker="systools">systools(3)</seealso></p>
+ <title>See Also</title>
+ <p><seealso marker="doc/design_principles:users_guide">OTP Design Principles</seealso>,
+ <seealso marker="kernel:config"><c>config(4)</c></seealso>,
+ <seealso marker="rel"><c>rel(4)</c></seealso>,
+ <seealso marker="relup"><c>relup(4)</c></seealso>,
+ <seealso marker="script"><c>script(4)</c></seealso>,
+ <seealso marker="stdlib:sys"><c>sys(3)</c></seealso>,
+ <seealso marker="systools"><c>systools(3)</c></seealso></p>
</section>
</erlref>
diff --git a/lib/sasl/doc/src/relup.xml b/lib/sasl/doc/src/relup.xml
index 8eecf3fce2..58918fc8e8 100644
--- a/lib/sasl/doc/src/relup.xml
+++ b/lib/sasl/doc/src/relup.xml
@@ -36,59 +36,53 @@
<p>The <em>release upgrade file</em> describes how a release is
upgraded in a running system.</p>
<p>This file is automatically generated by
- <c>systools:make_relup/3,4</c>, using a release resource file
- (<c>.rel</c>), application resource files (<c>.app</c>) and
+ <seealso marker="systools#make_relup/3"><c>systools:make_relup/3,4</c></seealso>,
+ using a release resource file
+ (<c>.rel</c>), application resource files (<c>.app</c>), and
application upgrade files (<c>.appup</c>) as input.</p>
</description>
<section>
- <title>FILE SYNTAX</title>
- <p>In a target system, the release upgrade file should be located in
- the <c>OTP_ROOT/erts-EVsn/Vsn</c> directory.</p>
+ <title>File Syntax</title>
+ <p>In a target system, the release upgrade file is to be located in
+ directory <c>$ROOT/releases/Vsn</c>.</p>
<p>The <c>relup</c> file contains one single Erlang term, which
defines the instructions used to upgrade the release. The file has
the following syntax:</p>
<code type="none">
{Vsn,
[{UpFromVsn, Descr, Instructions}, ...],
- [{DownToVsn, Descr, Instructions}, ...]}.
- </code>
- <list type="bulleted">
- <item>
- <p><c>Vsn = string()</c> is the current version of the release.</p>
- </item>
- <item>
- <p><c>UpFromVsn = string()</c> is an earlier version of the release
- to upgrade from.</p>
- </item>
- <item>
- <p><c>Descr = term()</c> is a user defined parameter passed
- from the <c>systools:make_relup/3,4</c> function. It will
- be used in the return value of
- <c>release_handler:install_release/1,2</c>.</p>
- </item>
- <item>
- <p><c>Instructions</c> is a list of low-level release upgrade
- instructions, see <c>appup(4)</c>.</p>
- <p>It consists of the release upgrade instructions from
+ [{DownToVsn, Descr, Instructions}, ...]}.</code>
+ <taglist>
+ <tag><c>Vsn = string()</c></tag>
+ <item><p>Current release version.</p></item>
+ <tag><c>UpFromVsn = string()</c></tag>
+ <item><p>Earlier version of the release to upgrade from.</p></item>
+ <tag><c>Descr = term()</c></tag>
+ <item><p>A user-defined parameter passed
+ from the function
+ <seealso marker="systools#make_relup/3"><c>systools:make_relup/3,4</c></seealso>.
+ It is used in the return value of
+ <seealso marker="release_handler#install_release/1"><c>release_handler:install_release/1,2</c></seealso>.</p></item>
+ <tag><c>Instructions</c></tag>
+ <item><p>A list of low-level release upgrade instructions, see
+ <seealso marker="appup"><c>appup(4)</c></seealso>.
+ It consists of the release upgrade instructions from
the respective application upgrade files (high-level instructions
are translated to low-level instructions), in the same order
- as in the start script.</p>
- </item>
- <item>
- <p><c>DownToVsn = string()</c> is an earlier version of the release
- to downgrade to.</p>
- </item>
- </list>
- <p>When upgrading from <c>UpFromVsn</c> with
- <c>release_handler:install_release/1,2</c>, there does not have to be
- an exact match of versions, but <c>UpFromVsn</c> can be a sub-string
- of the current release version.</p>
+ as in the start script.</p></item>
+ <tag><c>DownToVsn = string()</c></tag>
+ <item><p>Earlier version of the release to downgrade to.</p></item>
+ </taglist>
</section>
<section>
- <title>SEE ALSO</title>
- <p>app(4), appup(4), rel(4), release_handler(3), systools(3)</p>
+ <title>See Also</title>
+ <p><seealso marker="kernel:app"><c>app(4)</c></seealso>,
+ <seealso marker="appup"><c>appup(4)</c></seealso>,
+ <seealso marker="rel"><c>rel(4)</c></seealso>,
+ <seealso marker="release_handler"><c>release_handler(3)</c></seealso>,
+ <seealso marker="systools"><c>systools(3)</c></seealso></p>
</section>
</fileref>
diff --git a/lib/sasl/doc/src/sasl_app.xml b/lib/sasl/doc/src/sasl_app.xml
index fe38e69ce3..8d79251c7e 100644
--- a/lib/sasl/doc/src/sasl_app.xml
+++ b/lib/sasl/doc/src/sasl_app.xml
@@ -27,12 +27,11 @@
<docno></docno>
<date></date>
<rev></rev>
- </header>
- <app>sasl</app>
- <appsummary>The SASL Application</appsummary>
- <description>
- <p>This section describes the SASL (System Architecture Support Libraries)
- application which provides the following services:</p>
+ </header>
+ <app>sasl</app>
+ <appsummary>The SASL application</appsummary>
+ <description>
+ <p>The <c>SASL</c> application provides the following services:</p>
<list type="bulleted">
<item><c>alarm_handler</c></item>
<item><c>overload</c></item>
@@ -40,138 +39,147 @@
<item><c>release_handler</c></item>
<item><c>systools</c></item>
</list>
- <p>The SASL application also includes <c>error_logger</c> event
- handlers for formatting SASL error and crash reports.</p>
-
+ <p>The <c>SASL</c> application also includes <c>error_logger</c> event
+ handlers for formatting <c>SASL</c> error and crash reports.</p>
<note>
- <p>The SASL application in OTP has nothing to do with
+ <p>The <c>SASL</c> application in OTP has nothing to do with
"Simple Authentication and Security Layer" (RFC 4422).</p>
</note>
-
</description>
<section>
<title>Error Logger Event Handlers</title>
<p>The following error logger event handlers are used by
- the SASL application.</p>
+ the <c>SASL</c> application.</p>
<taglist>
<tag><c>sasl_report_tty_h</c></tag>
<item>
- <p>Formats and writes <em>supervisor reports</em>, <em>crash reports</em> and <em>progress reports</em> to <c>stdio</c>.
- This error logger event handler will use
+ <p>Formats and writes <em>supervisor reports</em>, <em>crash
+ reports</em>, and <em>progress reports</em> to <c>stdio</c>.
+ This error logger event handler uses
<seealso marker="kernel:kernel_app#error_logger_format_depth">error_logger_format_depth</seealso>
- in the Kernel application to limit how much detail are printed to
- for crash and supervisor reports.</p>
+ in the <c>Kernel</c> application to limit how much detail is
+ printed in crash and supervisor reports.</p>
</item>
<tag><c>sasl_report_file_h</c></tag>
<item>
- <p>Formats and writes <em>supervisor reports</em>, <em>crash report</em> and <em>progress report</em> to a single file.
- This error logger event handler will use
+ <p>Formats and writes <em>supervisor reports</em>, <em>crash
+ report</em>, and <em>progress report</em> to a single file.
+ This error logger event handler uses
<seealso marker="kernel:kernel_app#error_logger_format_depth">error_logger_format_depth</seealso>
- in the Kernel application to limit how much detail are printed to
- for crash and supervisor reports.</p>
+ in the <c>Kernel</c> application to limit the details
+ printed in crash and supervisor reports.</p>
</item>
<tag><c>log_mf_h</c></tag>
<item>
- <p>This error logger writes <em>all</em> events sent to
- the error logger to disk.</p>
- <p>To activate this event handler, the following three sasl
- configuration parameters must be set:
- <c>error_logger_mf_dir</c>, <c>error_logger_mf_maxbytes</c>
- and <c>error_logger_mf_maxfiles</c>. See below for more
- information about the configuration parameters.</p>
+ <p>This error logger writes <em>all</em> events sent to the
+ error logger to disk. Multiple files and log rotation are
+ used. For efficiency reasons, each event is written as a
+ binary. For more information about this handler,
+ see <seealso marker="stdlib:log_mf_h">the <c>STDLIB</c> Reference
+ Manual</seealso>.</p>
+ <p>To activate this event handler, three <c>SASL</c>
+ configuration parameters must be set,
+ <c>error_logger_mf_dir</c>, <c>error_logger_mf_maxbytes</c>,
+ and <c>error_logger_mf_maxfiles</c>. The next section provides
+ more information about the configuration parameters.</p>
</item>
</taglist>
</section>
<section>
<title>Configuration</title>
- <p>The following configuration parameters are defined for the SASL
- application. See <c>app(4)</c> for more information about
- configuration parameters:</p>
+ <p>The following configuration parameters are defined for the <c>SASL</c>
+ application. For more information about configuration parameters, see
+ <seealso marker="kernel:app"><c>app(4)</c></seealso> in <c>Kernel</c>.</p>
+ <p>All configuration parameters are optional.</p>
<taglist>
- <tag><c><![CDATA[sasl_error_logger = Value <optional>]]></c></tag>
+ <tag><c><![CDATA[sasl_error_logger = Value ]]></c></tag>
<item>
- <p><c>Value</c> is one of:</p>
+ <p><c>Value</c> is one of the following:</p>
<taglist>
<tag><c>tty</c></tag>
- <item>Installs <c>sasl_report_tty_h</c> in the error logger.
- This is the default option.</item>
+ <item><p>Installs <c>sasl_report_tty_h</c> in the error logger.
+ This is the default option.</p></item>
<tag><c>{file,FileName}</c></tag>
- <item>Installs <c>sasl_report_file_h</c> in the error logger.
- This makes all reports go to the file <c>FileName</c>.
- <c>FileName</c> is a string.</item>
+ <item><p>Installs <c>sasl_report_file_h</c> in the error logger.
+ All reports go to file <c>FileName</c>, which is a
+ string.</p></item>
<tag><c>{file,FileName,Modes}</c></tag>
- <item>Same as <c>{file,FileName}</c> except that the <c>Modes</c>
- allows to specify the modes used for opening the <c>FileName</c>
- given to the <seealso marker="kernel:file#open/2">file:open/2</seealso>
- call. When not specified, the <c>Modes</c> defaults to <c>[write]</c>.
- Use <c>[append]</c> for having the <c>FileName</c> open in append mode.
- <c>FileName</c> is a string.</item>
+ <item><p>Same as <c>{file,FileName}</c>, except that <c>Modes</c>
+ allows you to specify the modes used for opening the <c>FileName</c>
+ given to the <seealso marker="kernel:file#open/2">file:open/2</seealso>
+ call. When not specified, <c>Modes</c> defaults to <c>[write]</c>.
+ Use <c>[append]</c> to have the <c>FileName</c> open in append mode.
+ <c>FileName</c> is a string.</p></item>
<tag><c>false</c></tag>
- <item>
- <p>No SASL error logger handler is installed.</p>
- </item>
+ <item><p>No <c>SASL</c> error logger handler is installed.</p></item>
</taglist>
</item>
- <tag><c><![CDATA[errlog_type = error | progress | all <optional>]]></c></tag>
+ <tag><c><![CDATA[errlog_type = error | progress | all ]]></c></tag>
<item>
<p>Restricts the error logging performed by the specified
- <c>sasl_error_logger</c> to error reports, progress reports,
+ <c>sasl_error_logger</c> to error reports or progress reports,
or both. Default is <c>all</c>.</p>
</item>
- <tag><c><![CDATA[error_logger_mf_dir = string() | false<optional>]]></c></tag>
+ <tag><c><![CDATA[error_logger_mf_dir = string() | false ]]></c></tag>
<item>
- <p>Specifies in which directory the files are stored. If this
- parameter is undefined or <c>false</c>,
+ <p>Specifies in which directory <c>log_mf_h</c> is to store
+ its files. If this parameter is undefined or <c>false</c>,
the <c>log_mf_h</c> handler is not installed.</p>
</item>
- <tag><c><![CDATA[error_logger_mf_maxbytes = integer() <optional>]]></c></tag>
+ <tag><c><![CDATA[error_logger_mf_maxbytes = integer() ]]></c></tag>
<item>
- <p>Specifies how large each individual file can be. If this
- parameter is undefined, the <c>log_mf_h</c> handler is not
- installed.</p>
+ <p>Specifies the maximum size of each individual file written
+ by <c>log_mf_h</c>. If this parameter is undefined,
+ the <c>log_mf_h</c> handler is not installed.</p>
</item>
- <tag><c><![CDATA[error_logger_mf_maxfiles = 0<integer()<256 <optional>]]></c></tag>
+ <tag><c><![CDATA[error_logger_mf_maxfiles = 0<integer()<256 ]]></c></tag>
<item>
- <p>Specifies how many files are used. If this parameter is
- undefined, the <c>log_mf_h</c> handler is not installed.</p>
+ <p>Specifies the number of files used by <c>log_mf_h</c>. If
+ this parameter is undefined, the <c>log_mf_h</c> handler is
+ not installed.</p>
</item>
- <tag><c><![CDATA[overload_max_intensity = float() > 0 <optional>]]></c></tag>
+ <tag><c><![CDATA[overload_max_intensity = float() > 0 ]]></c></tag>
<item>
- <p>Specifies the maximum intensity for <c>overload</c>. Default
+ <p>Specifies the maximum intensity
+ for <seealso marker="overload"><c>overload</c></seealso>. Default
is <c>0.8</c>.</p>
</item>
- <tag><c><![CDATA[overload_weight = float() > 0 <optional>]]></c></tag>
+ <tag><c><![CDATA[overload_weight = float() > 0 ]]></c></tag>
<item>
- <p>Specifies the <c>overload</c> weight. Default is <c>0.1</c>.</p>
+ <p>Specifies the <seealso marker="overload"><c>overload</c></seealso>
+ weight. Default is <c>0.1</c>.</p>
</item>
- <tag><c><![CDATA[start_prg = string() <optional>]]></c></tag>
+ <tag><c><![CDATA[start_prg = string() ]]></c></tag>
<item>
- <p>Specifies which program should be used when restarting
- the system. Default is <c>$OTP_ROOT/bin/start</c>.</p>
+ <p>Specifies the program to be used when restarting the system
+ during release installation. Default is
+ <c>$OTP_ROOT/bin/start</c>.</p>
</item>
- <tag><c><![CDATA[masters = [atom()] <optional>]]></c></tag>
+ <tag><c><![CDATA[masters = [atom()] ]]></c></tag>
<item>
- <p>Specifies which nodes this node uses to read/write release
- information. This parameter is ignored if
- the <c>client_directory</c> parameter is not set.</p>
+ <p>Specifies the nodes used by this node to read/write release
+ information. This parameter is ignored if parameter
+ <c>client_directory</c> is not set.</p>
</item>
- <tag><c><![CDATA[client_directory = string() <optional>]]></c></tag>
+ <tag><c><![CDATA[client_directory = string() ]]></c></tag>
<item>
<p>This parameter specifies the client directory at the master
- nodes. Refer to Release Handling in <em>OTP Design Principles</em> for more information. This parameter is
- ignored if the <c>masters</c> parameter is not set.</p>
+ nodes. For details, see
+ <seealso marker="doc/design_principles:release_handling">Release Handling</seealso>
+ in <em>OTP Design Principles</em>. This parameter is
+ ignored if parameter <c>masters</c> is not set.</p>
</item>
- <tag><c><![CDATA[static_emulator = true | false <optional>]]></c></tag>
+ <tag><c><![CDATA[static_emulator = true | false ]]></c></tag>
<item>
<p>Indicates if the Erlang emulator is statically installed. A
node with a static emulator cannot switch dynamically to a
- new emulator as the executable files are written into memory
- statically. This parameter is ignored if the <c>masters</c>
- and <c>client_directory</c> parameters are not set.</p>
+ new emulator, as the executable files are written into memory
+ statically. This parameter is ignored if parameters <c>masters</c>
+ and <c>client_directory</c> are not set.</p>
</item>
- <tag><c><![CDATA[releases_dir = string() <optional>]]></c></tag>
+ <tag><c><![CDATA[releases_dir = string() ]]></c></tag>
<item>
<p>Indicates where the <c>releases</c> directory is located.
The release handler writes all its files to this directory.
@@ -179,7 +187,7 @@
<c>RELDIR</c> is used. By default, this is
<c>$OTP_ROOT/releases</c>.</p>
</item>
- <tag><c><![CDATA[utc_log = true | false <optional>]]></c></tag>
+ <tag><c><![CDATA[utc_log = true | false ]]></c></tag>
<item>
<p>If set to <c>true</c>, all dates in textual log outputs are
displayed in Universal Coordinated Time with the string
@@ -190,13 +198,13 @@
<section>
<title>See Also</title>
- <p><seealso marker="alarm_handler">alarm_handler(3)</seealso>,
- error_logger(3),
- log_mf_h(3),
- <seealso marker="overload">overload(3)</seealso>,
- <seealso marker="rb">rb(3)</seealso>,
- <seealso marker="release_handler">release_handler(3)</seealso>,
- <seealso marker="systools">systools(3)</seealso></p>
+ <p><seealso marker="alarm_handler"><c>alarm_handler(3)</c></seealso>,
+ <seealso marker="kernel:error_logger"><c>error_logger(3)</c></seealso>,
+ <seealso marker="stdlib:log_mf_h"><c>log_mf_h(3)</c></seealso>,
+ <seealso marker="overload"><c>overload(3)</c></seealso>,
+ <seealso marker="rb"><c>rb(3)</c></seealso>,
+ <seealso marker="release_handler"><c>release_handler(3)</c></seealso>,
+ <seealso marker="systools"><c>systools(3)</c></seealso></p>
</section>
</appref>
diff --git a/lib/sasl/doc/src/sasl_intro.xml b/lib/sasl/doc/src/sasl_intro.xml
index 2dc3efebc1..bbc9457103 100644
--- a/lib/sasl/doc/src/sasl_intro.xml
+++ b/lib/sasl/doc/src/sasl_intro.xml
@@ -31,22 +31,32 @@
</header>
<section>
- <title>About This Document</title>
- <p>The SASL (System Architecture Support Libraries)
- application provides support for:</p>
+ <title>Scope</title>
+ <p>The <c>SASL</c> application provides support for:</p>
<list type="bulleted">
- <item>error logging</item>
- <item>alarm handling</item>
- <item>overload regulation</item>
- <item>release handling</item>
- <item>report browsing.</item>
+ <item>Error logging</item>
+ <item>Alarm handling</item>
+ <item>Overload regulation</item>
+ <item>Release handling</item>
+ <item>Report browsing</item>
</list>
- <p>In this document, "SASL Error Logging" describes the error
- handler which produces the supervisor, progress, and crash
- reports which can be written to screen, or to a specified file.
- It also describes the report browser <c>rb</c>.</p>
- <p>The chapters about release structure and release handling have
- been moved to <em>OTP Design Principles</em>.</p>
+ <p>Section
+ <seealso marker="error_logging">SASL Error Logging</seealso>
+ describes the error
+ handler that produces the supervisor, progress, and crash
+ reports, which can be written to screen or to a specified file.
+ It also describes the Report Browser (RB).</p>
+ <p>The sections about release structure and release handling have
+ been moved to section
+ <seealso marker="doc/design_principles:users_guide">OTP Design Principles</seealso>
+ in <em>System Documentation</em>.</p>
</section>
+
+ <section>
+ <title>Prerequisites</title>
+ <p>It is assumed that the reader is familiar with the Erlang
+ programming language.</p>
+ </section>
+
</chapter>
diff --git a/lib/sasl/doc/src/script.xml b/lib/sasl/doc/src/script.xml
index 838efe69bb..db3ea0f487 100644
--- a/lib/sasl/doc/src/script.xml
+++ b/lib/sasl/doc/src/script.xml
@@ -37,25 +37,21 @@
<file>script</file>
<filesummary>Boot script</filesummary>
<description>
- <p>The <em>boot script</em> describes how the Erlang runtime system is
- started. It contains instructions on which code to load and
- which processes and applications to start.
- </p>
- <p>The command <c>erl -boot Name</c> starts the system with a boot
+ <p>The <em>boot script</em> describes how the Erlang runtime system
+ is started. It contains instructions on which code to load and
+ which processes and applications to start.</p>
+ <p>Command <c>erl -boot Name</c> starts the system with a boot
file called <c>Name.boot</c>, which is generated from the
- <c>Name.script</c> file, using <c>systools:script2boot/1</c>.
- </p>
+ <c>Name.script</c> file, using
+ <seealso marker="systools#script2boot/1"><c>systools:script2boot/1</c></seealso>.</p>
<p>The <c>.script</c> file is generated by <c>systools</c> from a
- <c>.rel</c> file and <c>.app</c> files.
- </p>
+ <c>.rel</c> file and from <c>.app</c> files.</p>
</description>
<section>
- <title>FILE SYNTAX</title>
- <p>The boot script is stored in a file with the extension
- <c>.script</c></p>
- <p>The file has the following syntax:
- </p>
+ <title>File Syntax</title>
+ <p>The boot script is stored in a file with extension
+ <c>.script</c>. The file has the following syntax:</p>
<code type="none">
{script, {Name, Vsn},
[
@@ -70,100 +66,97 @@
...
{apply, {Mod, Func, Args}},
...
- {progress, started}]}. </code>
- <list type="bulleted">
- <item><c>Name = string()</c> defines the name of the system.
- </item>
- <item><c>Vsn = string()</c> defines the version of the system.
- </item>
- <item><c>{progress, Term}</c> sets the "progress" of the
- initialization program. The function <c>init:get_status()</c>
- returns the current value of the progress, which is
- <c>{InternalStatus,Term}</c>.
- </item>
- <item>
- <p><c>{path, [Dir]}</c> where <c>Dir</c> is a string. This
+ {progress, started}]}.</code>
+ <taglist>
+ <tag><c>Name = string()</c></tag>
+ <item><p>Defines the system name.</p></item>
+ <tag><c>Vsn = string()</c></tag>
+ <item><p>Defines the system version.</p></item>
+ <tag><c>{progress, Term}</c></tag>
+ <item><p>Sets the "progress" of the initialization
+ program. The
+ <seealso marker="erts:init#get_status/0"><c>init:get_status/0</c></seealso>
+ function returns the current value of the progress, which is
+ <c>{InternalStatus,Term}</c>.</p></item>
+ <tag><c>{path, [Dir]}</c></tag>
+ <item><p><c>Dir</c> is a string. This
argument sets the load path of the system to <c>[Dir]</c>. The
load path used to load modules is obtained from the initial
load path, which is given in the script file, together with
- any path flags which were supplied in the command line
- arguments. The command line arguments modify the path as
+ any path flags that were supplied in the command-line
+ arguments. The command-line arguments modify the path as
follows:</p>
<list type="bulleted">
<item><c>-pa Dir1 Dir2 ... DirN</c> adds the directories
<c>Dir1, Dir2, ..., DirN</c> to the front of the initial
- load path.
- </item>
+ load path.</item>
<item><c>-pz Dir1 Dir2 ... DirN</c> adds the directories
<c>Dir1, Dir2, ..., DirN</c> to the end of the initial
- load path.
- </item>
+ load path.</item>
<item>
<p><c>-path Dir1 Dir2 ... DirN</c> defines a set of
- directories <c>Dir1, Dir2, ..., DirN</c> which replaces
+ directories <c>Dir1, Dir2, ..., DirN</c>, which replace
the search path given in the script file. Directory names
in the path are interpreted as follows:</p>
<list type="bulleted">
<item>Directory names starting with <c>/</c> are assumed
- to be absolute path names.
- </item>
+ to be absolute path names.</item>
<item>Directory names not starting with <c>/</c> are
- assumed to be relative the current working directory.
- </item>
+ assumed to be relative the current working directory.</item>
<item>The special <c>$ROOT</c> variable can only be used
- in the script, not as a command line argument. The
+ in the script, not as a command-line argument. The
given directory is relative the Erlang installation
- directory.
- </item>
+ directory.</item>
</list>
</item>
</list>
- </item>
- <item><c>{primLoad, [Mod]}</c> loads the modules <c>[Mod]</c>
- from the directories specified in <c>Path</c>. The script
- interpreter fetches the appropriate module by calling the
- function <c>erl_prim_loader:get_file(Mod)</c>. A fatal error
- which terminates the system will occur if the module cannot be
- located.
- </item>
- <item><c>{kernel_load_completed}</c> indicates that all modules
- which <em>must</em> be loaded <em>before</em> any processes
- are started are loaded. In interactive mode, all
- <c>{primLoad,[Mod]}</c> commands interpreted after this
- command are ignored, and these modules are loaded on demand.
- In embedded mode, <c>kernel_load_completed</c> is ignored, and
- all modules are loaded during system start.
- </item>
- <item><c>{kernelProcess, Name, {Mod, Func, Args}}</c> starts a
- "kernel process". The kernel process <c>Name</c> is started
- by evaluating <c>apply(Mod, Func, Args)</c> which is expected
- to return <c>{ok, Pid}</c> or <c>ignore</c>. The <c>init</c>
- process monitors the behaviour of <c>Pid</c> and terminates
- the system if <c>Pid</c> dies. Kernel processes are key
- components of the runtime system. Users do not normally add
- new kernel processes.
- </item>
- <item><c>{apply, {Mod, Func, Args}}</c>. The init process simply
- evaluates <c>apply(Mod, Func, Args)</c>. The system
- terminates if this results in an error. The boot procedure
- hangs if this function never returns.
- </item>
- </list>
+ </item>
+ <tag><c>{primLoad, [Mod]}</c></tag>
+ <item><p>Loads the modules <c>[Mod]</c>
+ from the directories specified in <c>Path</c>. The script
+ interpreter fetches the appropriate module by calling
+ <seealso marker="erts:erl_prim_loader#get_file/1">
+ <c>erl_prim_loader:get_file(Mod)</c></seealso>. A fatal error
+ that terminates the system occurs if the module cannot be
+ located.</p></item>
+ <tag><c>{kernel_load_completed}</c></tag>
+ <item><p>Indicates that all modules
+ that <em>must</em> be loaded <em>before</em> any processes
+ are started are loaded. In interactive mode, all
+ <c>{primLoad,[Mod]}</c> commands interpreted after this
+ command are ignored, and these modules are loaded on demand.
+ In embedded mode, <c>kernel_load_completed</c> is ignored, and
+ all modules are loaded during system start.</p></item>
+ <tag><c>{kernelProcess, Name, {Mod, Func, Args}}</c></tag>
+ <item><p>Starts the
+ "kernel process" <c>Name</c>
+ by evaluating <c>apply(Mod, Func, Args)</c>. The start function is
+ to return <c>{ok, Pid}</c> or <c>ignore</c>. The <c>init</c>
+ process monitors the behavior of <c>Pid</c> and terminates
+ the system if <c>Pid</c> dies. Kernel processes are key
+ components of the runtime system. Users do not normally add
+ new kernel processes.</p></item>
+ <tag><c>{apply, {Mod, Func, Args}}</c>.</tag>
+ <item><p>The init process
+ evaluates <c>apply(Mod, Func, Args)</c>. The system
+ terminates if this results in an error. The boot procedure
+ hangs if this function never returns.</p></item>
+ </taglist>
<note>
- <p>In the <c>interactive</c> system the code loader provides
- demand driven code loading, but in the <c>embedded</c> system
- the code loader loads all the code immediately. The same
- version of <c>code</c> is used in both cases. The code server
- calls <c>init:get_argument(mode)</c> to find out if it should
- run in demand mode, or non-demand driven mode.
- </p>
+ <p>In an interactive system, the code loader provides
+ demand-driven code loading, but in an embedded system
+ the code loader loads all code immediately. The same
+ version of <seealso marker="kernel:code"><c>code</c></seealso>
+ is used in both cases. The code server calls
+ <seealso marker="erts:init#get_argument/1"><c>init:get_argument(mode)</c></seealso>
+ to determine if it is to run in demand mode or non-demand
+ driven mode.</p>
</note>
</section>
<section>
- <title>SEE ALSO</title>
- <p>systools(3)
- </p>
+ <title>See Also</title>
+ <p><seealso marker="systools"><c>systools(3)</c></seealso></p>
</section>
</fileref>
diff --git a/lib/sasl/doc/src/systools.xml b/lib/sasl/doc/src/systools.xml
index 11d99fa595..1a5119a5cf 100644
--- a/lib/sasl/doc/src/systools.xml
+++ b/lib/sasl/doc/src/systools.xml
@@ -31,17 +31,18 @@
<rev></rev>
</header>
<module>systools</module>
- <modulesummary>A Set of Release Handling Tools.</modulesummary>
+ <modulesummary>A Set of Release Handling Tools</modulesummary>
<description>
<p>This module contains functions to generate boot scripts
- (<c>.boot</c>, <c>.script</c>), release upgrade scripts
+ (<c>.boot</c>, <c>.script</c>), a release upgrade file
(<c>relup</c>), and release packages.</p>
</description>
+
<funcs>
<func>
<name>make_relup(Name, UpFrom, DownTo) -> Result</name>
<name>make_relup(Name, UpFrom, DownTo, [Opt]) -> Result</name>
- <fsummary>Generate a release upgrade file <c>relup</c>.</fsummary>
+ <fsummary>Generates a release upgrade file <c>relup</c>.</fsummary>
<type>
<v>Name = string()</v>
<v>UpFrom = DownTo = [Name | {Name,Descr}]</v>
@@ -50,93 +51,94 @@
| warnings_as_errors</v>
<v>&nbsp;Dir = string()</v>
<v>Result = ok | error | {ok,Relup,Module,Warnings} | {error,Module,Error}</v>
- <v>&nbsp;Relup - see relup(4)</v>
+ <v>&nbsp;Relup, see relup(4)</v>
<v>&nbsp;Module = atom()</v>
<v>&nbsp;Warnings = Error = term()</v>
</type>
<desc>
- <p>Generates a release upgrade file <c>relup</c> containing a
- script which describes how to upgrade the system from a number
- of previous releases, and how to downgrade to a number of
- previous releases. The script is used by
- <c>release_handler</c> when installing a new version of a
- release in run-time.</p>
- <p>By default, <c>relup</c> is placed in the current working
- directory. If the option <c>{outdir,Dir}</c> is provided,
- <c>relup</c> is placed in <c>Dir</c> instead.</p>
+ <p>Generates a release upgrade file <c>relup</c> containing instructions
+ for upgrading from or downgrading to one or more previous releases.
+ The instructions are used by
+ <seealso marker="release_handler"><c>release_handler</c></seealso>
+ when installing a new version of a release in runtime.</p>
+ <p>By default, <c>relup</c> file is located in the current working
+ directory. If option <c>{outdir,Dir}</c> is specified,
+ the <c>relup</c> file is located in <c>Dir</c> instead.</p>
<p>The release resource file <c>Name.rel</c> is compared with
- all release resource files <c>Name2.rel</c> specified in
- <c>UpFrom</c> and <c>DownTo</c>. For each such pair, it is
- deducted:</p>
+ all release resource files <c>Name2.rel</c>, specified in
+ <c>UpFrom</c> and <c>DownTo</c>. For each such pair, the
+ following is deducted:</p>
<list type="bulleted">
<item>
- <p>Which applications should be deleted, that is
- applications which are listed in <c>Name.rel</c> but not
- in <c>Name2.rel</c>.</p>
+ <p>Which applications to be deleted, that is,
+ applications listed in <c>Name.rel</c> but not
+ in <c>Name2.rel</c></p>
</item>
<item>
- <p>Which applications should be added, that is applications
- which are listed in <c>Name2.rel</c> but not in
- <c>Name.rel</c>.</p>
+ <p>Which applications to be added, that is, applications
+ listed in <c>Name2.rel</c> but not in <c>Name.rel</c></p>
</item>
<item>
- <p>Which applications should be upgraded/downgraded, that
- is applications listed in both <c>Name.rel</c> and
- <c>Name2.rel</c>, but with different versions.</p>
+ <p>Which applications to be upgraded/downgraded, that
+ is, applications listed in both <c>Name.rel</c> and
+ <c>Name2.rel</c> but with different versions</p>
</item>
<item>
<p>If the emulator needs to be restarted after upgrading or
- downgrading, that is if the ERTS version differs between
- <c>Name.rel</c> and <c>Name2.rel</c>.</p>
+ downgrading, that is, if the <c>ERTS</c> version differs
+ between <c>Name.rel</c> and <c>Name2.rel</c></p>
</item>
</list>
- <p>Instructions for this are added to the <c>relup</c> script in
+ <p>Instructions for this are added to the <c>relup</c> file in
the above order. Instructions for upgrading or downgrading
between application versions are fetched from the relevant
application upgrade files <c>App.appup</c>, sorted in
the same order as when generating a boot script, see
- <c>make_script/1,2</c>. High-level instructions are translated
- into low-level instructions and the result is printed to
- <c>relup</c>.</p>
- <p>The optional <c>Descr</c> parameter is included as-is in
- the <c>relup</c> script, see <c>relup(4)</c>. Defaults to
+ <seealso marker="#make_script/1"><c>make_script/1,2</c></seealso>.
+ High-level instructions are translated
+ into low-level instructions and the result is printed to the
+ <c>relup</c> file.</p>
+ <p>The optional <c>Descr</c> parameter is included "as is" in
+ the <c>relup</c> file, see
+ <seealso marker="relup"><c>relup(4)</c></seealso>. Defaults to
the empty list.</p>
<p>All the files are searched for in the code path. It is
- assumed that the <c>.app</c> and <c>.appup</c> file for an
- application is located in the same directory.</p>
- <p>If the option <c>{path,[Dir]}</c> is provided, this path is
- appended to the current path. The wildcard <c>*</c> is
- expanded to all matching directories.
- Example: <c>lib/*/ebin</c>.</p>
- <p>If the <c>restart_emulator</c> option is supplied, a
+ assumed that the <c>.app</c> and <c>.appup</c> files for an
+ application are located in the same directory.</p>
+ <p>If option <c>{path,[Dir]}</c> is specified, this path is
+ appended to the current path. Wildcard <c>*</c> is
+ expanded to all matching directories, for example,
+ <c>lib/*/ebin</c>.</p>
+ <p>If option <c>restart_emulator</c> is specified, a
low-level instruction to restart the emulator is appended to
- the relup scripts. This ensures that a complete reboot of
+ the <c>relup</c> file. This ensures that a complete reboot of
the system is done when the system is upgraded or downgraded.</p>
- <p>If an upgrade includes a change from an emulator earlier
- than OTP R15 to OTP R15 or later, the warning
- <c>pre_R15_emulator_upgrade</c> is issued. See <seealso
- marker="doc/design_principles:appup_cookbook">Design
- Principles</seealso> for more information about this.</p>
+ <p>If an upgrade includes a change from an emulator earlier
+ than OTP R15 to OTP R15 or later, the warning
+ <c>pre_R15_emulator_upgrade</c> is issued. For more information
+ about this, see
+ <seealso marker="doc/design_principles:appup_cookbook">Design
+ Principles</seealso> in <em>System Documentation</em>.</p>
<p>By default, errors and warnings are printed to tty and
- the function returns <c>ok</c> or <c>error</c>. If the option
- <c>silent</c> is provided, the function instead returns
- <c>{ok,Relup,Module,Warnings}</c> where <c>Relup</c> is
- the release upgrade script, or it returns
- <c>{error,Module,Error}</c>. Warnings and errors can be
- converted to strings by calling
+ the function returns <c>ok</c> or <c>error</c>. If option
+ <c>silent</c> is specified, the function instead either returns
+ <c>{ok,Relup,Module,Warnings}</c>, where <c>Relup</c> is
+ the release upgrade file, or <c>{error,Module,Error}</c>.
+ Warnings and errors can be converted to strings by calling
<c>Module:format_warning(Warnings)</c> or
<c>Module:format_error(Error)</c>.</p>
- <p>If the option <c>noexec</c> is provided, the function returns
+ <p>If option <c>noexec</c> is specified, the function returns
the same values as for <c>silent</c> but no <c>relup</c> file
is created.</p>
- <p>If the option <c>warnings_as_errors</c> is provided, warnings
- are treated as errors.</p>
+ <p>If option <c>warnings_as_errors</c> is specified, warnings
+ are treated as errors.</p>
</desc>
</func>
+
<func>
<name>make_script(Name) -> Result</name>
<name>make_script(Name, [Opt]) -> Result</name>
- <fsummary>Generate a boot script <c>.script/.boot</c>.</fsummary>
+ <fsummary>Generates a boot script <c>.script/.boot</c>.</fsummary>
<type>
<v>Name = string()</v>
<v>Opt = src_tests | {path,[Dir]} | local | {variables,[Var]} | exref |
@@ -153,114 +155,117 @@
<desc>
<p>Generates a boot script <c>Name.script</c> and its binary
version, the boot file <c>Name.boot</c>. The boot file
- specifies which code should be loaded and which applications
- should be started when the Erlang runtime system is started.
- See <c>script(4)</c>.</p>
- <p>The release resource file <c>Name.rel</c> is read to find
- out which applications are included in the release. Then
- the relevant application resource files <c>App.app</c> are
- read to find out which modules should be loaded and if and
- how the application should be started. (Keys <c>modules</c>
- and <c>mod</c>, see <c>app(4)</c>).</p>
- <p>By default, the boot script and boot file are placed in
+ specifies which code to be loaded and which applications
+ to be started when the Erlang runtime system is started.
+ See <seealso marker="script"><c>script(4)</c></seealso>.</p>
+ <p>The release resource file <c>Name.rel</c> is read to determine
+ which applications are included in the release. Then
+ the relevant application resource files <c>App.app</c> are read
+ to determine which modules to be loaded, and if and
+ how the applications are to be started. (Keys <c>modules</c>
+ and <c>mod</c>, see
+ <seealso marker="kernel:app"><c>app(4)</c></seealso>.</p>
+ <p>By default, the boot script and boot file are located in
the same directory as <c>Name.rel</c>. That is, in the current
working directory unless <c>Name</c> contains a path. If
- the option <c>{outdir,Dir}</c> is provided, they are placed
+ option <c>{outdir,Dir}</c> is specified, they are located
in <c>Dir</c> instead.</p>
- <p>The correctness of each application is checked:</p>
+ <p>The correctness of each application is checked as follows:</p>
<list type="bulleted">
<item>
<p>The version of an application specified in
- the <c>.rel</c> file should be the same as the version
+ the <c>.rel</c> file is to be the same as the version
specified in the <c>.app</c> file.</p>
</item>
<item>
- <p>There should be no undefined applications, that is,
- dependencies to applications which are not included in
- the release. (Key <c>applications</c> in <c>.app</c>
+ <p>There are to be no undefined applications, that is,
+ dependencies to applications that are not included in
+ the release. (Key <c>applications</c> in the <c>.app</c>
file).</p>
</item>
<item>
- <p>There should be no circular dependencies among
+ <p>There are to be no circular dependencies among
the applications.</p>
</item>
<item>
- <p>There should be no duplicated modules, that is, modules with
+ <p>There are to be no duplicated modules, that is, modules with
the same name but belonging to different applications.</p>
</item>
<item>
- <p>If the <c>src_tests</c> option is specified, a
+ <p>If option <c>src_tests</c> is specified, a
warning is issued if the source code for a module is
- missing or newer than the object code.</p>
+ missing or is newer than the object code.</p>
</item>
</list>
<p>The applications are sorted according to the dependencies
between the applications. Where there are no dependencies,
the order in the <c>.rel</c> file is kept.</p>
- <p>The function will fail if the mandatory
- applications <c>kernel</c> and <c>stdlib</c> are not
- included in the <c>.rel</c> file and have start
- type <c>permanent</c> (default).</p>
- <p>If <c>sasl</c> is not included as an application in
- the <c>.rel</c> file, a warning is emitted because such a
- release can not be used in an upgrade. To turn off this
- warning, add the option <c>no_warn_sasl</c>.</p>
+ <p>The function fails if the mandatory
+ applications <c>Kernel</c> and <c>STDLIB</c> are not
+ included in the <c>.rel</c> file and have start
+ type <c>permanent</c> (which is default).</p>
+ <p>If <c>SASL</c> is not included as an application in
+ the <c>.rel</c> file, a warning is issued because such a
+ release cannot be used in an upgrade. To turn off this
+ warning, add option <c>no_warn_sasl</c>.</p>
<p>All files are searched for in the current path. It is
assumed that the <c>.app</c> and <c>.beam</c> files for an
- application is located in the same directory. The <c>.erl</c>
+ application are located in the same directory. The <c>.erl</c>
files are also assumed to be located in this directory, unless
- it is an <c>ebin</c> directory in which case they may be
+ it is an <c>ebin</c> directory in which case they can be
located in the corresponding <c>src</c> directory.</p>
- <p>If the option <c>{path,[Dir]}</c> is provided, this path is
+ <p>If option <c>{path,[Dir]}</c> is specified, this path is
appended to the current path. A directory in the path can be
- given with a wildcard <c>*</c>, this is expanded to all
+ specified with a wildcard <c>*</c>, this is expanded to all
matching directories. Example: <c>"lib/*/ebin"</c>.</p>
<p>In the generated boot script all application directories are
- structured as <c>App-Vsn/ebin</c> and assumed to be located
+ structured as <c>App-Vsn/ebin</c>. They are assumed to be located
in <c>$ROOT/lib</c>, where <c>$ROOT</c> is the root directory
- of the installed release. If the <c>local</c> option is
- supplied, the actual directories where the applications were
+ of the installed release. If option <c>local</c> is
+ specified, the actual directories where the applications were
found are used instead. This is a useful way to test a
generated boot script locally.</p>
- <p>The <c>variables</c> option can be used to specify an
+ <p>Option <c>variables</c> can be used to specify an
installation directory other than <c>$ROOT/lib</c> for some of
the applications. If a variable <c>{VarName,Prefix}</c> is
specified and an application is found in a directory
- <c>Prefix/Rest/App[-Vsn]/ebin</c>, this application will get
+ <c>Prefix/Rest/App[-Vsn]/ebin</c>, this application gets
the path <c>VarName/Rest/App-Vsn/ebin</c> in the boot script.
If an application is found in a directory <c>Prefix/Rest</c>,
- the path will be <c>VarName/Rest/App-Vsn/ebin</c>. When
+ the path is <c>VarName/Rest/App-Vsn/ebin</c>. When
starting Erlang, all variables <c>VarName</c> are given
- values using the <c>boot_var</c> command line flag.</p>
- <p>Example: If the option <c>{variables,[{"TEST","lib"}]}</c> is
- supplied, and <c>myapp.app</c> is found in
- <c>lib/myapp/ebin</c>, then the path to this application in
- the boot script will be <c>"$TEST/myapp-1/ebin"</c>. If
- <c>myapp.app</c> is found in <c>lib/test</c>, then the path
- will be <c>$TEST/test/myapp-1/ebin</c>.</p>
+ values using command-line flag <c>boot_var</c>.</p>
+ <p><em>Example:</em> If option <c>{variables,[{"TEST","lib"}]}</c>
+ is specified and <c>myapp.app</c> is found in
+ <c>lib/myapp/ebin</c>, the path to this application in
+ the boot script is <c>"$TEST/myapp-1/ebin"</c>. If
+ <c>myapp.app</c> is found in <c>lib/test</c>, the path
+ is <c>$TEST/test/myapp-1/ebin</c>.</p>
<p>The checks performed before the boot script is generated can
be extended with some cross reference checks by specifying
- the <c>exref</c> option. These checks are performed with
+ option <c>exref</c>. These checks are performed with
the Xref tool. All applications, or the applications specified
with <c>{exref,[App]}</c>, are checked by Xref and
- warnings are generated for calls to undefined functions.</p>
+ warnings are issued for calls to undefined functions.</p>
<p>By default, errors and warnings are printed to tty and
- the function returns <c>ok</c> or <c>error</c>. If the option
- <c>silent</c> is provided, the function instead returns
+ the function returns <c>ok</c> or <c>error</c>. If option
+ <c>silent</c> is specified, the function instead returns
<c>{ok,Module,Warnings}</c> or <c>{error,Module,Error}</c>.
Warnings and errors can be converted to strings by calling
<c>Module:format_warning(Warnings)</c> or
<c>Module:format_error(Error)</c>.</p>
- <p>If the option <c>warnings_as_errors</c> is provided, warnings
- are treated as errors.</p>
- <p>If the option <c>no_dot_erlang</c> is provided, the instruction to
- load the <c>.erlang</c> file during boot is <em>NOT</em> included.</p>
+ <p>If option <c>warnings_as_errors</c> is specified, warnings
+ are treated as errors.</p>
+ <p>If option <c>no_dot_erlang</c> is specified, the instruction to
+ load the <c>.erlang</c> file during boot is <em>not</em>
+ included.</p>
</desc>
</func>
+
<func>
<name>make_tar(Name) -> Result</name>
<name>make_tar(Name, [Opt]) -> Result</name>
- <fsummary>Create a release package.</fsummary>
+ <fsummary>Creates a release package.</fsummary>
<type>
<v>Name = string()</v>
<v>Opt = {dirs,[IncDir]} | {path,[Dir]} | {variables,[Var]} | {var_tar,VarTar} | {erts,Dir} | src_tests | exref | {exref,[App]} | silent | {outdir,Dir}</v>
@@ -276,90 +281,91 @@
<v>&nbsp;Warning = Error = term()</v>
</type>
<desc>
- <p>Creates a release package file <c>Name.tar.gz</c>. file.
+ <p>Creates a release package file <c>Name.tar.gz</c>.
This file must be uncompressed and unpacked on the target
- system using the <c>release_handler</c>, before the new
- release can be installed.</p>
- <p>The release resource file <c>Name.rel</c> is read to find out
+ system using
+ <seealso marker="release_handler"><c>release_handler</c></seealso>
+ before the new release can be installed.</p>
+ <p>The release resource file <c>Name.rel</c> is read to determine
which applications are included in the release. Then
the relevant application resource files <c>App.app</c> are
- read to find out the version and modules of each application.
- (Keys <c>vsn</c> and <c>modules</c>, see <c>app(4)</c>).</p>
- <p>By default, the release package file is placed in the same
+ read to determine the version and modules of each application
+ (keys <c>vsn</c> and <c>modules</c>, see
+ <seealso marker="kernel:app"><c>app(4)</c></seealso>).</p>
+ <p>By default, the release package file is located in the same
directory as <c>Name.rel</c>. That is, in the current working
- directory unless <c>Name</c> contains a path. If the option
- <c>{outdir,Dir}</c> is provided, it is placed in <c>Dir</c>
+ directory unless <c>Name</c> contains a path. If option
+ <c>{outdir,Dir}</c> is specified, it is located in <c>Dir</c>
instead.</p>
<p>By default, the release package contains the directories
<c>lib/App-Vsn/ebin</c> and <c>lib/App-Vsn/priv</c> for each
- included application. If more directories, the option
- <c>dirs</c> is supplied. Example:
+ included application. If more directories are to be included,
+ option <c>dirs</c> is specified, for example,
<c>{dirs,[src,examples]}</c>.</p>
<p>All these files are searched for in the current path. If
- the option <c>{path,[Dir]}</c> is provided, this path is
- appended to the current path. The wildcard <c>*</c> is
+ option <c>{path,[Dir]}</c> is specified, this path is
+ appended to the current path. Wildcard <c>*</c> is
expanded to all matching directories.
Example: <c>"lib/*/ebin"</c>.</p>
- <p>The <c>variables</c> option can be used to specify an
+ <p>Option <c>variables</c> can be used to specify an
installation directory other than <c>lib</c> for some of
- the applications. If a variable <c>{VarName,Prefix}</c> is
- specified and an application is found in a directory
- <c>Prefix/Rest/App[-Vsn]/ebin</c>, this application will be
+ the applications. If variable <c>{VarName,Prefix}</c> is
+ specified and an application is found in directory
+ <c>Prefix/Rest/App[-Vsn]/ebin</c>, this application is
packed into a separate <c>VarName.tar.gz</c> file as
<c>Rest/App-Vsn/ebin</c>.</p>
- <p>Example: If the option <c>{variables,[{"TEST","lib"}]}</c> is
- supplied, and <c>myapp.app</c> is found in
- <c>lib/myapp-1/ebin</c>, the the application <c>myapp</c> is
+ <p><em>Example:</em> If option <c>{variables,[{"TEST","lib"}]}</c>
+ is specified and <c>myapp.app</c> is located in
+ <c>lib/myapp-1/ebin</c>, application <c>myapp</c> is
included in <c>TEST.tar.gz</c>:</p>
<pre>
% <input>tar tf TEST.tar</input>
myapp-1/ebin/myapp.app
-...
- </pre>
- <p>The <c>{var_tar,VarTar}</c> option can be used to specify if
- and where a separate package should be stored. In this option,
- <c>VarTar</c> is:</p>
- <list type="bulleted">
- <item>
- <p><c>include</c>. Each separate (variable) package is
- included in the main <c>ReleaseName.tar.gz</c> file. This
- is the default.</p>
- </item>
- <item>
- <p><c>ownfile</c>. Each separate (variable) package is
- generated as separate files in the same directory as
- the <c>ReleaseName.tar.gz</c> file.</p>
- </item>
- <item>
- <p><c>omit</c>. No separate (variable) packages are
- generated and applications which are found underneath a
- variable directory are ignored.</p>
- </item>
- </list>
- <p>A directory called <c>releases</c> is also included in
+...</pre>
+ <p>Option <c>{var_tar,VarTar}</c> can be used to specify if
+ and where a separate package is to be stored. In this option
+ <c>VarTar</c> is one of the following:</p>
+ <taglist>
+ <tag><c>include</c></tag>
+ <item><p>Each separate (variable) package is included in the
+ main <c>ReleaseName.tar.gz</c> file. This is the
+ default.</p></item>
+ <tag><c>ownfile</c></tag>
+ <item><p>Each separate (variable) package is
+ generated as a separate file in the same directory as
+ the <c>ReleaseName.tar.gz</c> file.</p></item>
+ <tag><c>omit</c></tag>
+ <item><p>No separate (variable) packages are
+ generated. Applications that are found underneath a
+ variable directory are ignored.</p></item>
+ </taglist>
+ <p>A directory <c>releases</c> is also included in
the release package, containing <c>Name.rel</c> and a
- subdirectory called <c>RelVsn</c>. <c>RelVsn</c> is
+ subdirectory <c>RelVsn</c>. <c>RelVsn</c> is
the release version as specified in <c>Name.rel</c>.</p>
<p><c>releases/RelVsn</c> contains the boot script
<c>Name.boot</c> renamed to <c>start.boot</c> and, if found,
the files <c>relup</c> and <c>sys.config</c>. These files
are searched for in the same directory as <c>Name.rel</c>,
in the current working directory, and in any directories
- specified using the <c>path</c> option.</p>
- <p>If the release package should contain a new Erlang runtime
+ specified using option <c>path</c>.</p>
+ <p>If the release package is to contain a new Erlang runtime
system, the <c>bin</c> directory of the specified runtime
system <c>{erts,Dir}</c> is copied to <c>erts-ErtsVsn/bin</c>.</p>
- <p>All checks performed with the <c>make_script</c> function
- are performed before the release package is created. The
- <c>src_tests</c> and <c>exref</c> options are also
+ <p>All checks with function
+ <seealso marker="#make_script/1"><c>make_script</c></seealso>
+ are performed before the release package is created.
+ Options <c>src_tests</c> and <c>exref</c> are also
valid here.</p>
<p>The return value and the handling of errors and warnings
- are the same as described for <c>make_script</c> above.</p>
+ are the same as described for
+ <seealso marker="#make_script/1"><c>make_script</c></seealso>.</p>
</desc>
</func>
+
<func>
<name>script2boot(File) -> ok | error</name>
- <fsummary>Generate a binary version of a boot script.</fsummary>
+ <fsummary>Generates a binary version of a boot script.</fsummary>
<type>
<v>File = string()</v>
</type>
@@ -367,17 +373,24 @@ myapp-1/ebin/myapp.app
<p>The Erlang runtime system requires that the contents of
the script used to boot the system is a binary Erlang term.
This function transforms the <c>File.script</c> boot script
- to a binary term which is stored in the file <c>File.boot</c>.</p>
- <p>A boot script generated using the <c>make_script</c>
- function is already transformed to the binary form.</p>
+ to a binary term, which is stored in the <c>File.boot</c>
+ file.</p>
+ <p>A boot script generated using
+ <seealso marker="#make_script/1"><c>make_script</c></seealso>
+ is already transformed to the binary form.</p>
</desc>
</func>
</funcs>
<section>
- <title>SEE ALSO</title>
- <p>app(4), appup(4), erl(1), rel(4), release_handler(3), relup(4),
- script(4)</p>
+ <title>See Also</title>
+ <p><seealso marker="kernel:app"><c>app(4)</c></seealso>,
+ <seealso marker="appup"><c>appup(4)</c></seealso>,
+ <seealso marker="erts:erl"><c>erl(1)</c></seealso>,
+ <seealso marker="rel"><c>rel(4)</c></seealso>,
+ <seealso marker="release_handler"><c>release_handler(3)</c></seealso>,
+ <seealso marker="relup"><c>relup(4)</c></seealso>,
+ <seealso marker="script"><c>script(4)</c></seealso></p>
</section>
</erlref>
diff --git a/lib/snmp/doc/src/snmp_agent_netif.xml b/lib/snmp/doc/src/snmp_agent_netif.xml
index 769fd23115..9583f1f521 100644
--- a/lib/snmp/doc/src/snmp_agent_netif.xml
+++ b/lib/snmp/doc/src/snmp_agent_netif.xml
@@ -76,8 +76,7 @@
<c>{Domain, Addr}</c> tuple where <c>Domain</c> is
<c>transportDomainUdpIpv4</c> or <c>transportDomainUdpIpv4</c>,
and <c>Addr</c> is an
- <c>{<seealso marker="kernel:inet#type-ip_address">IpAddr</seealso>,
- IpPort}</c> tuple.</p>
+ <c>{</c><seealso marker="kernel:inet#type-ip_address"><c>IpAddr</c></seealso><c>,IpPort}</c> tuple.</p>
<section>
<marker id="outgoing_messages"></marker>
diff --git a/lib/snmp/doc/src/snmp_app.xml b/lib/snmp/doc/src/snmp_app.xml
index 234a076eda..39aac8e7d7 100644
--- a/lib/snmp/doc/src/snmp_app.xml
+++ b/lib/snmp/doc/src/snmp_app.xml
@@ -135,16 +135,16 @@
<marker id="agent_opts_and_types"></marker>
<p>Agent specific config options and types:</p>
<taglist>
- <marker id="agent_type"></marker>
- <tag><c><![CDATA[agent_type() = master | sub <optional>]]></c></tag>
+ <tag><marker id="agent_type"></marker>
+ <c><![CDATA[agent_type() = master | sub <optional>]]></c></tag>
<item>
<p>If <c>master</c>, one master agent is
started. Otherwise, no agents are started. </p>
<p>Default is <c>master</c>.</p>
</item>
- <marker id="agent_disco"></marker>
- <tag><c><![CDATA[agent_discovery() = [agent_discovery_opt()] <optional>]]></c></tag>
+ <tag><marker id="agent_disco"></marker>
+ <c><![CDATA[agent_discovery() = [agent_discovery_opt()] <optional>]]></c></tag>
<item>
<p><c>agent_discovery_opt() =
{terminating, agent_terminating_discovery_opts()} |
@@ -156,8 +156,8 @@
<p>For defaults see the options in <c>agent_discovery_opt()</c>.</p>
</item>
- <marker id="agent_term_disco_opts"></marker>
- <tag><c><![CDATA[agent_terminating_discovery_opts() = [agent_terminating_discovery_opt()] <optional>]]></c></tag>
+ <tag><marker id="agent_term_disco_opts"></marker>
+ <c><![CDATA[agent_terminating_discovery_opts() = [agent_terminating_discovery_opt()] <optional>]]></c></tag>
<item>
<p><c>agent_terminating_discovery_opt() =
{enable, boolean()} |
@@ -174,8 +174,8 @@
</list>
</item>
- <marker id="agent_orig_disco_opts"></marker>
- <tag><c><![CDATA[agent_originating_discovery_opts() = [agent_originating_discovery_opt()] <optional>]]></c></tag>
+ <tag><marker id="agent_orig_disco_opts"></marker>
+ <c><![CDATA[agent_originating_discovery_opts() = [agent_originating_discovery_opt()] <optional>]]></c></tag>
<item>
<p><c>agent_originating_discovery_opt() =
{enable, boolean()}</c></p>
@@ -188,38 +188,39 @@
</list>
</item>
- <marker id="agent_mt"></marker>
- <tag><c><![CDATA[multi_threaded() = bool() <optional>]]></c></tag>
+ <tag><marker id="agent_mt"></marker>
+ <c><![CDATA[multi_threaded() = bool() <optional>]]></c></tag>
<item>
<p>If <c>true</c>, the agent is multi-threaded, with one
thread for each get request. </p>
<p>Default is <c>false</c>.</p>
</item>
- <marker id="agent_data_dir"></marker>
- <tag><c><![CDATA[db_dir() = string() <mandatory>]]></c></tag>
+ <tag><marker id="agent_data_dir"></marker>
+ <c><![CDATA[db_dir() = string() <mandatory>]]></c></tag>
<item>
<p>Defines where the SNMP agent internal db files are stored.</p>
</item>
- <marker id="agent_gb_max_vbs"></marker>
- <tag><c><![CDATA[gb_max_vbs() = pos_integer() | infinity <optional>]]></c></tag>
+
+ <tag><marker id="agent_gb_max_vbs"></marker>
+ <c><![CDATA[gb_max_vbs() = pos_integer() | infinity <optional>]]></c></tag>
<item>
<p>Defines the maximum number of varbinds allowed
in a Get-BULK response.</p>
<p>Default is <c>1000</c>.</p>
</item>
- <marker id="agent_local_db"></marker>
- <tag><c><![CDATA[local_db() = [local_db_opt()] <optional>]]></c></tag>
+ <tag><marker id="agent_local_db"></marker>
+ <c><![CDATA[local_db() = [local_db_opt()] <optional>]]></c></tag>
<item>
<p><c>local_db_opt() = {repair, agent_repair()} | {auto_save, agent_auto_save()} | {verbosity, verbosity()}</c></p>
<p>Defines options specific for the SNMP agent local database.</p>
<p>For defaults see the options in <c>local_db_opt()</c>.</p>
</item>
- <marker id="agent_ldb_repair"></marker>
- <tag><c><![CDATA[agent_repair() = false | true | force <optional>]]></c></tag>
+ <tag><marker id="agent_ldb_repair"></marker>
+ <c><![CDATA[agent_repair() = false | true | force <optional>]]></c></tag>
<item>
<p>When starting snmpa_local_db it always tries to open an
existing database. If <c>false</c>, and some errors occur, a new
@@ -229,16 +230,16 @@
<p>Default is <c>true</c>.</p>
</item>
- <marker id="agent_ldb_auto_save"></marker>
- <tag><c><![CDATA[agent_auto_save() = integer() | infinity <optional>]]></c></tag>
+ <tag><marker id="agent_ldb_auto_save"></marker>
+ <c><![CDATA[agent_auto_save() = integer() | infinity <optional>]]></c></tag>
<item>
<p>The auto save interval. The table is flushed to disk
whenever not accessed for this amount of time.</p>
<p>Default is <c>5000</c>.</p>
</item>
- <marker id="agent_net_if"></marker>
- <tag><c><![CDATA[agent_net_if() = [agent_net_if_opt()] <optional>]]></c></tag>
+ <tag><marker id="agent_net_if"></marker>
+ <c><![CDATA[agent_net_if() = [agent_net_if_opt()] <optional>]]></c></tag>
<item>
<p><c>agent_net_if_opt() = {module, agent_net_if_module()} | {verbosity, verbosity()} | {options, agent_net_if_options()}</c></p>
<p>Defines options specific for the SNMP agent network interface
@@ -246,8 +247,8 @@
<p>For defaults see the options in <c>agent_net_if_opt()</c>.</p>
</item>
- <marker id="agent_ni_module"></marker>
- <tag><c><![CDATA[agent_net_if_module() = atom() <optional>]]></c></tag>
+ <tag><marker id="agent_ni_module"></marker>
+ <c><![CDATA[agent_net_if_module() = atom() <optional>]]></c></tag>
<item>
<p>Module which handles the network interface part for the
SNMP agent. Must implement the
@@ -255,8 +256,8 @@
<p>Default is <c>snmpa_net_if</c>.</p>
</item>
- <marker id="agent_ni_opts"></marker>
- <tag><c><![CDATA[agent_net_if_options() = [agent_net_if_option()] <optional>]]></c></tag>
+ <tag><marker id="agent_ni_opts"></marker>
+ <c><![CDATA[agent_net_if_options() = [agent_net_if_option()] <optional>]]></c></tag>
<item>
<p><c>agent_net_if_option() = {bind_to, bind_to()} |
{sndbuf, sndbuf()} |
@@ -270,15 +271,15 @@
<p>For defaults see the options in <c>agent_net_if_option()</c>.</p>
</item>
- <marker id="agent_ni_req_limit"></marker>
- <tag><c><![CDATA[req_limit() = integer() | infinity <optional>]]></c></tag>
+ <tag><marker id="agent_ni_req_limit"></marker>
+ <c><![CDATA[req_limit() = integer() | infinity <optional>]]></c></tag>
<item>
<p>Max number of simultaneous requests handled by the agent.</p>
<p>Default is <c>infinity</c>.</p>
</item>
- <marker id="agent_ni_filter_opts"></marker>
- <tag><c><![CDATA[agent_net_if_filter_options() = [agent_net_if_filter_option()] <optional>]]></c></tag>
+ <tag><marker id="agent_ni_filter_opts"></marker>
+ <c><![CDATA[agent_net_if_filter_options() = [agent_net_if_filter_option()] <optional>]]></c></tag>
<item>
<p><c>agent_net_if_filter_option() = {module, agent_net_if_filter_module()}</c></p>
<p>These options are actually specific to the used module.
@@ -288,8 +289,8 @@
<c>agent_net_if_filter_option()</c>.</p>
</item>
- <marker id="agent_ni_filter_module"></marker>
- <tag><c><![CDATA[agent_net_if_filter_module() = atom() <optional>]]></c></tag>
+ <tag><marker id="agent_ni_filter_module"></marker>
+ <c><![CDATA[agent_net_if_filter_module() = atom() <optional>]]></c></tag>
<item>
<p>Module which handles the network interface filter part for the
SNMP agent. Must implement the
@@ -297,8 +298,8 @@
<p>Default is <c>snmpa_net_if_filter</c>.</p>
</item>
- <marker id="agent_mibs"></marker>
- <tag><c><![CDATA[agent_mibs() = [string()] <optional>]]></c></tag>
+ <tag><marker id="agent_mibs"></marker>
+ <c><![CDATA[agent_mibs() = [string()] <optional>]]></c></tag>
<item>
<p>Specifies a list of MIBs (including path) that defines which MIBs
are initially loaded into the SNMP master agent. </p>
@@ -312,8 +313,8 @@
<p>Default is <c>[]</c>.</p>
</item>
- <marker id="agent_mib_storage"></marker>
- <tag><c><![CDATA[mib_storage() = [mib_storage_opt()] <optional>]]></c></tag>
+ <tag><marker id="agent_mib_storage"></marker>
+ <c><![CDATA[mib_storage() = [mib_storage_opt()] <optional>]]></c></tag>
<item>
<p><c>mib_storage_opt() = {module, mib_storage_module()} | {options, mib_storage_options()}</c></p>
<p>This option specifies how basic mib data is stored.
@@ -322,8 +323,8 @@
<p>Default is <c>[{module, snmpa_mib_storage_ets}]</c>. </p>
</item>
- <marker id="agent_mst_module"></marker>
- <tag><c><![CDATA[mib_storage_module() = snmpa_mib_data_ets | snmpa_mib_data_dets | snmpa_mib_data_mnesia | module()]]></c></tag>
+ <tag><marker id="agent_mst_module"></marker>
+ <c><![CDATA[mib_storage_module() = snmpa_mib_data_ets | snmpa_mib_data_dets | snmpa_mib_data_mnesia | module()]]></c></tag>
<item>
<p>Defines the mib storage module of the SNMP agent as defined by the
<seealso marker="snmpa_mib_storage">snmpa_mib_storage</seealso>
@@ -337,8 +338,8 @@
<p>Default module is <c>snmpa_mib_storage_ets</c>. </p>
</item>
- <marker id="agent_mst_options"></marker>
- <tag><c><![CDATA[mib_storage_options() = list() <optional>]]></c></tag>
+ <tag><marker id="agent_mst_options"></marker>
+ <c><![CDATA[mib_storage_options() = list() <optional>]]></c></tag>
<item>
<p>This is implementattion depended. That is, it depends on the
module. For each module a specific set of options are valid.
@@ -427,16 +428,16 @@
</list>
</item>
- <marker id="agent_mib_server"></marker>
- <tag><c><![CDATA[mib_server() = [mib_server_opt()] <optional>]]></c></tag>
+ <tag><marker id="agent_mib_server"></marker>
+ <c><![CDATA[mib_server() = [mib_server_opt()] <optional>]]></c></tag>
<item>
<p><c>mib_server_opt() = {mibentry_override, mibentry_override()} | {trapentry_override, trapentry_override()} | {verbosity, verbosity()} | {cache, mibs_cache()} | {data_module, mib_server_data_module()}</c></p>
<p>Defines options specific for the SNMP agent mib server. </p>
<p>For defaults see the options in <c>mib_server_opt()</c>.</p>
</item>
- <marker id="agent_ms_meo"></marker>
- <tag><c><![CDATA[mibentry_override() = bool() <optional>]]></c></tag>
+ <tag><marker id="agent_ms_meo"></marker>
+ <c><![CDATA[mibentry_override() = bool() <optional>]]></c></tag>
<item>
<p>If this value is false, then when loading a mib each mib-
entry is checked prior to installation of the mib.
@@ -445,8 +446,8 @@
<p>Default is <c>false</c>.</p>
</item>
- <marker id="agent_ms_teo"></marker>
- <tag><c><![CDATA[trapentry_override() = bool() <optional>]]></c></tag>
+ <tag><marker id="agent_ms_teo"></marker>
+ <c><![CDATA[trapentry_override() = bool() <optional>]]></c></tag>
<item>
<p>If this value is false, then when loading a mib each trap
is checked prior to installation of the mib.
@@ -455,11 +456,12 @@
<p>Default is <c>false</c>.</p>
</item>
- <marker id="agent_ms_data_module"></marker>
<!--
- <tag><c><![CDATA[mib_server_data_module() = snmpa_mib_data_tttn | snmpa_mib_data_ttln | module() <optional>]]></c></tag>
+ <tag><marker id="agent_ms_data_module"></marker>
+ <c><![CDATA[mib_server_data_module() = snmpa_mib_data_tttn | snmpa_mib_data_ttln | module() <optional>]]></c></tag>
-->
- <tag><c><![CDATA[mib_server_data_module() = snmpa_mib_data_tttn | module() <optional>]]></c></tag>
+ <tag><marker id="agent_ms_data_module"></marker>
+ <c><![CDATA[mib_server_data_module() = snmpa_mib_data_tttn | module() <optional>]]></c></tag>
<item>
<p>Defines the backend data module of the SNMP agent mib-server as
defined by the
@@ -476,24 +478,24 @@
<p>Default module is <c>snmpa_mib_data_tttn</c>. </p>
</item>
- <marker id="agent_ms_cache"></marker>
- <tag><c><![CDATA[mibs_cache() = bool() | mibs_cache_opts() <optional>]]></c></tag>
+ <tag><marker id="agent_ms_cache"></marker>
+ <c><![CDATA[mibs_cache() = bool() | mibs_cache_opts() <optional>]]></c></tag>
<item>
<p>Shall the agent utilize the mib server lookup cache or not.</p>
<p>Default is <c>true</c> (in which case the <c>mibs_cache_opts()</c>
default values apply).</p>
</item>
- <marker id="agent_ms_cache_opts"></marker>
- <tag><c><![CDATA[mibs_cache_opts() = [mibs_cache_opt()] <optional>]]></c></tag>
+ <tag><marker id="agent_ms_cache_opts"></marker>
+ <c><![CDATA[mibs_cache_opts() = [mibs_cache_opt()] <optional>]]></c></tag>
<item>
<p><c>mibs_cache_opt() = {autogc, mibs_cache_autogc()} | {gclimit, mibs_cache_gclimit()} | {age, mibs_cache_age()}</c></p>
<p>Defines options specific for the SNMP agent mib server cache. </p>
<p>For defaults see the options in <c>mibs_cache_opt()</c>.</p>
</item>
- <marker id="agent_ms_cache_autogc"></marker>
- <tag><c><![CDATA[mibs_cache_autogc() = bool() <optional>]]></c></tag>
+ <tag><marker id="agent_ms_cache_autogc"></marker>
+ <c><![CDATA[mibs_cache_autogc() = bool() <optional>]]></c></tag>
<item>
<p>Defines if the mib server shall perform cache gc automatically or
leave it to the user (see
@@ -501,8 +503,8 @@
<p>Default is <c>true</c>.</p>
</item>
- <marker id="agent_ms_cache_age"></marker>
- <tag><c><![CDATA[mibs_cache_age() = integer() > 0 <optional>]]></c></tag>
+ <tag><marker id="agent_ms_cache_age"></marker>
+ <c><![CDATA[mibs_cache_age() = integer() > 0 <optional>]]></c></tag>
<item>
<p>Defines how old the entries in the cache will be allowed
to become before they are GC'ed (assuming GC is performed).
@@ -511,8 +513,8 @@
<p>Default is <c>10 timutes</c>.</p>
</item>
- <marker id="agent_ms_cache_gclimit"></marker>
- <tag><c><![CDATA[mibs_cache_gclimit() = integer() > 0 | infinity <optional>]]></c></tag>
+ <tag><marker id="agent_ms_cache_gclimit"></marker>
+ <c><![CDATA[mibs_cache_gclimit() = integer() > 0 | infinity <optional>]]></c></tag>
<item>
<p>When performing a GC, this is the max number of cache entries
that will be deleted from the cache. </p>
@@ -522,8 +524,8 @@
<p>Default is <c>100</c>.</p>
</item>
- <marker id="agent_error_report_mod"></marker>
- <tag><c><![CDATA[error_report_mod() = atom() <optional>]]></c></tag>
+ <tag><marker id="agent_error_report_mod"></marker>
+ <c><![CDATA[error_report_mod() = atom() <optional>]]></c></tag>
<item>
<p>Defines an error report module, implementing the
<seealso marker="snmpa_error_report">snmpa_error_report</seealso>
@@ -532,38 +534,38 @@
<p>Default is <c>snmpa_error_logger</c>.</p>
</item>
- <marker id="agent_symbolic_store"></marker>
- <tag><c>symbolic_store() = [symbolic_store_opt()]</c></tag>
+ <tag><marker id="agent_symbolic_store"></marker>
+ <c>symbolic_store() = [symbolic_store_opt()]</c></tag>
<item>
<p><c>symbolic_store_opt() = {verbosity, verbosity()}</c></p>
<p>Defines options specific for the SNMP agent symbolic store. </p>
<p>For defaults see the options in <c>symbolic_store_opt()</c>.</p>
</item>
- <marker id="agent_target_cache"></marker>
- <tag><c>target_cache() = [target_cache_opt()]</c></tag>
+ <tag><marker id="agent_target_cache"></marker>
+ <c>target_cache() = [target_cache_opt()]</c></tag>
<item>
<p><c>target_cache_opt() = {verbosity, verbosity()}</c></p>
<p>Defines options specific for the SNMP agent target cache. </p>
<p>For defaults see the options in <c>target_cache_opt()</c>.</p>
</item>
- <marker id="agent_config"></marker>
- <tag><c><![CDATA[agent_config() = [agent_config_opt()] <mandatory>]]></c></tag>
+ <tag><marker id="agent_config"></marker>
+ <c><![CDATA[agent_config() = [agent_config_opt()] <mandatory>]]></c></tag>
<item>
<p><c>agent_config_opt() = {dir, agent_config_dir()} | {force_load, force_load()} | {verbosity, verbosity()}</c></p>
<p>Defines specific config related options for the SNMP agent. </p>
<p>For defaults see the options in <c>agent_config_opt()</c>.</p>
</item>
- <marker id="agent_config_dir"></marker>
- <tag><c><![CDATA[agent_config_dir = dir() <mandatory>]]></c></tag>
+ <tag><marker id="agent_config_dir"></marker>
+ <c><![CDATA[agent_config_dir = dir() <mandatory>]]></c></tag>
<item>
<p>Defines where the SNMP agent configuration files are stored.</p>
</item>
- <marker id="agent_force_load"></marker>
- <tag><c><![CDATA[force_load() = bool() <optional>]]></c></tag>
+ <tag><marker id="agent_force_load"></marker>
+ <c><![CDATA[force_load() = bool() <optional>]]></c></tag>
<item>
<p>If <c>true</c> the configuration files are re-read
during start-up, and the contents of the configuration
@@ -577,16 +579,16 @@
<marker id="manager_opts_and_types"></marker>
<p>Manager specific config options and types:</p>
<taglist>
- <marker id="manager_server"></marker>
- <tag><c><![CDATA[server() = [server_opt()] <optional>]]></c></tag>
+ <tag><marker id="manager_server"></marker>
+ <c><![CDATA[server() = [server_opt()] <optional>]]></c></tag>
<item>
<p><c>server_opt() = {timeout, server_timeout()} | {verbosity, verbosity()}</c></p>
<p>Specifies the options for the manager server process.</p>
<p>Default is <c>silence</c>.</p>
</item>
- <marker id="manager_server_timeout"></marker>
- <tag><c><![CDATA[server_timeout() = integer() <optional>]]></c></tag>
+ <tag><marker id="manager_server_timeout"></marker>
+ <c><![CDATA[server_timeout() = integer() <optional>]]></c></tag>
<item>
<p>Asynchronous request cleanup time. For every requests,
some info is stored internally, in order to be able to
@@ -606,44 +608,44 @@
<p>Default is <c>30000</c>.</p>
</item>
- <marker id="manager_config"></marker>
- <tag><c><![CDATA[manager_config() = [manager_config_opt()] <mandatory>]]></c></tag>
+ <tag><marker id="manager_config"></marker>
+ <c><![CDATA[manager_config() = [manager_config_opt()] <mandatory>]]></c></tag>
<item>
<p><c>manager_config_opt() = {dir, manager_config_dir()} | {db_dir, manager_db_dir()} | {db_init_error, db_init_error()} | {repair, manager_repair()} | {auto_save, manager_auto_save()} | {verbosity, verbosity()}</c></p>
<p>Defines specific config related options for the SNMP manager. </p>
<p>For defaults see the options in <c>manager_config_opt()</c>.</p>
</item>
- <marker id="manager_config_dir"></marker>
- <tag><c><![CDATA[manager_config_dir = dir() <mandatory>]]></c></tag>
+ <tag><marker id="manager_config_dir"></marker>
+ <c><![CDATA[manager_config_dir = dir() <mandatory>]]></c></tag>
<item>
<p>Defines where the SNMP manager configuration files are stored.</p>
</item>
- <marker id="manager_config_db_dir"></marker>
- <tag><c><![CDATA[manager_db_dir = dir() <mandatory>]]></c></tag>
+ <tag><marker id="manager_config_db_dir"></marker>
+ <c><![CDATA[manager_db_dir = dir() <mandatory>]]></c></tag>
<item>
<p>Defines where the SNMP manager store persistent data.</p>
</item>
- <marker id="manager_config_repair"></marker>
- <tag><c><![CDATA[manager_repair() = false | true | force <optional>]]></c></tag>
+ <tag><marker id="manager_config_repair"></marker>
+ <c><![CDATA[manager_repair() = false | true | force <optional>]]></c></tag>
<item>
<p>Defines the repair option for the persistent database (if
and how the table is repaired when opened). </p>
<p>Default is <c>true</c>.</p>
</item>
- <marker id="manager_config_auto_save"></marker>
- <tag><c><![CDATA[manager_auto_save() = integer() | infinity <optional>]]></c></tag>
+ <tag><marker id="manager_config_auto_save"></marker>
+ <c><![CDATA[manager_auto_save() = integer() | infinity <optional>]]></c></tag>
<item>
<p>The auto save interval. The table is flushed to disk
whenever not accessed for this amount of time.</p>
<p>Default is <c>5000</c>.</p>
</item>
- <marker id="manager_irb"></marker>
- <tag><c><![CDATA[manager_irb() = auto | user | {user, integer()} <optional>]]></c></tag>
+ <tag><marker id="manager_irb"></marker>
+ <c><![CDATA[manager_irb() = auto | user | {user, integer()} <optional>]]></c></tag>
<item>
<p>This option defines how the manager will handle the sending of
response (acknowledgment) to received inform-requests. </p>
@@ -672,16 +674,16 @@
<p>Default is <c>auto</c>.</p>
</item>
- <marker id="manager_mibs"></marker>
- <tag><c><![CDATA[manager_mibs() = [string()] <optional>]]></c></tag>
+ <tag><marker id="manager_mibs"></marker>
+ <c><![CDATA[manager_mibs() = [string()] <optional>]]></c></tag>
<item>
<p>Specifies a list of MIBs (including path) and defines which MIBs
are initially loaded into the SNMP manager. </p>
<p>Default is <c>[]</c>.</p>
</item>
- <marker id="manager_net_if"></marker>
- <tag><c><![CDATA[manager_net_if() = [manager_net_if_opt()] <optional>]]></c></tag>
+ <tag><marker id="manager_net_if"></marker>
+ <c><![CDATA[manager_net_if() = [manager_net_if_opt()] <optional>]]></c></tag>
<item>
<p><c>manager_net_if_opt() = {module, manager_net_if_module()} |
{verbosity, verbosity()} |
@@ -691,8 +693,8 @@
<p>For defaults see the options in <c>manager_net_if_opt()</c>.</p>
</item>
- <marker id="manager_ni_opts"></marker>
- <tag><c><![CDATA[manager_net_if_options() = [manager_net_if_option()] <optional>]]></c></tag>
+ <tag><marker id="manager_ni_opts"></marker>
+ <c><![CDATA[manager_net_if_options() = [manager_net_if_option()] <optional>]]></c></tag>
<item>
<p><c>manager_net_if_option() = {bind_to, bind_to()} |
{sndbuf, sndbuf()} |
@@ -705,8 +707,8 @@
<p>For defaults see the options in <c>manager_net_if_option()</c>.</p>
</item>
- <marker id="manager_ni_module"></marker>
- <tag><c><![CDATA[manager_net_if_module() = atom() <optional>]]></c></tag>
+ <tag><marker id="manager_ni_module"></marker>
+ <c><![CDATA[manager_net_if_module() = atom() <optional>]]></c></tag>
<item>
<p>The module which handles the network interface part for the
SNMP manager. It must implement the
@@ -714,8 +716,8 @@
<p>Default is <c>snmpm_net_if</c>.</p>
</item>
- <marker id="manager_ni_filter_opts"></marker>
- <tag><c><![CDATA[manager_net_if_filter_options() = [manager_net_if_filter_option()] <optional>]]></c></tag>
+ <tag><marker id="manager_ni_filter_opts"></marker>
+ <c><![CDATA[manager_net_if_filter_options() = [manager_net_if_filter_option()] <optional>]]></c></tag>
<item>
<p><c>manager_net_if_filter_option() = {module, manager_net_if_filter_module()}</c></p>
<p>These options are actually specific to the used module.
@@ -725,8 +727,8 @@
<c>manager_net_if_filter_option()</c>.</p>
</item>
- <marker id="manager_ni_filter_module"></marker>
- <tag><c><![CDATA[manager_net_if_filter_module() = atom() <optional>]]></c></tag>
+ <tag><marker id="manager_ni_filter_module"></marker>
+ <c><![CDATA[manager_net_if_filter_module() = atom() <optional>]]></c></tag>
<item>
<p>Module which handles the network interface filter part for the
SNMP manager. Must implement the
@@ -734,16 +736,16 @@
<p>Default is <c>snmpm_net_if_filter</c>.</p>
</item>
- <marker id="manager_def_user_module"></marker>
- <tag><c><![CDATA[def_user_module() = atom() <optional>]]></c></tag>
+ <tag><marker id="manager_def_user_module"></marker>
+ <c><![CDATA[def_user_module() = atom() <optional>]]></c></tag>
<item>
<p>The module implementing the default user. See the
<seealso marker="snmpm_user">snmpm_user</seealso> behaviour.</p>
<p>Default is <c>snmpm_user_default</c>.</p>
</item>
- <marker id="manager_def_user_data"></marker>
- <tag><c><![CDATA[def_user_data() = term() <optional>]]></c></tag>
+ <tag><marker id="manager_def_user_data"></marker>
+ <c><![CDATA[def_user_data() = term() <optional>]]></c></tag>
<item>
<p>Data for the default user. Passed to the user module when
calling the callback functions.</p>
@@ -754,8 +756,8 @@
<marker id="common_types"></marker>
<p>Common config types:</p>
<taglist>
- <marker id="restart_type"></marker>
- <tag><c>restart_type() = permanent | transient | temporary</c></tag>
+ <tag><marker id="restart_type"></marker>
+ <c>restart_type() = permanent | transient | temporary</c></tag>
<item>
<p>See <seealso marker="stdlib:supervisor#child_spec">supervisor</seealso>
documentation for more info.</p>
@@ -763,8 +765,8 @@
for the manager.</p>
</item>
- <marker id="db_init_error"></marker>
- <tag><c>db_init_error() = terminate | create | create_db_and_dir</c></tag>
+ <tag><marker id="db_init_error"></marker>
+ <c>db_init_error() = terminate | create | create_db_and_dir</c></tag>
<item>
<p>Defines what to do if the agent or manager is unable to open an
existing database file. <c>terminate</c> means that the
@@ -776,31 +778,31 @@
<p>Default is <c>terminate</c>.</p>
</item>
- <marker id="prio"></marker>
- <tag><c><![CDATA[priority() = atom() <optional>]]></c></tag>
+ <tag><marker id="prio"></marker>
+ <c><![CDATA[priority() = atom() <optional>]]></c></tag>
<item>
<p>Defines the Erlang priority for all SNMP processes.</p>
<p>Default is <c>normal</c>.</p>
</item>
- <marker id="versions"></marker>
- <tag><c><![CDATA[versions() = [version()] <optional>]]></c></tag>
+ <tag><marker id="versions"></marker>
+ <c><![CDATA[versions() = [version()] <optional>]]></c></tag>
<item>
<p><c>version() = v1 | v2 | v3</c></p>
<p>Which SNMP versions shall be accepted/used.</p>
<p>Default is <c>[v1,v2,v3]</c>.</p>
</item>
- <marker id="verbosity"></marker>
- <tag><c><![CDATA[verbosity() = silence | info | log | debug | trace <optional>]]></c></tag>
+ <tag><marker id="verbosity"></marker>
+ <c><![CDATA[verbosity() = silence | info | log | debug | trace <optional>]]></c></tag>
<item>
<p>Verbosity for a SNMP process. This specifies now much debug info
is printed.</p>
<p>Default is <c>silence</c>.</p>
</item>
- <marker id="bind_to"></marker>
- <tag><c><![CDATA[bind_to() = bool() <optional>]]></c></tag>
+ <tag><marker id="bind_to"></marker>
+ <c><![CDATA[bind_to() = bool() <optional>]]></c></tag>
<item>
<p>If <c>true</c>, net_if binds to the IP address.
If <c>false</c>, net_if listens on any IP address on the host
@@ -808,8 +810,8 @@
<p>Default is <c>false</c>.</p>
</item>
- <marker id="no_reuse"></marker>
- <tag><c><![CDATA[no_reuse() = bool() <optional>]]></c></tag>
+ <tag><marker id="no_reuse"></marker>
+ <c><![CDATA[no_reuse() = bool() <optional>]]></c></tag>
<item>
<p>If <c>true</c>, net_if does not specify that the IP
and port address should be reusable. If <c>false</c>,
@@ -817,30 +819,30 @@
<p>Default is <c>false</c>.</p>
</item>
- <marker id="recbuf"></marker>
- <tag><c><![CDATA[recbuf() = integer() <optional>]]></c></tag>
+ <tag><marker id="recbuf"></marker>
+ <c><![CDATA[recbuf() = integer() <optional>]]></c></tag>
<item>
<p>Receive buffer size. </p>
<p>Default value is defined by <c>gen_udp</c>.</p>
</item>
- <marker id="sndbuf"></marker>
- <tag><c><![CDATA[sndbuf() = integer() <optional>]]></c></tag>
+ <tag><marker id="sndbuf"></marker>
+ <c><![CDATA[sndbuf() = integer() <optional>]]></c></tag>
<item>
<p>Send buffer size. </p>
<p>Default value is defined by <c>gen_udp</c>.</p>
</item>
- <marker id="note_store"></marker>
- <tag><c><![CDATA[note_store() = [note_store_opt()] <optional>]]></c></tag>
+ <tag><marker id="note_store"></marker>
+ <c><![CDATA[note_store() = [note_store_opt()] <optional>]]></c></tag>
<item>
<p><c>note_store_opt() = {timeout, note_store_timeout()} | {verbosity, verbosity()}</c></p>
<p>Specifies the start-up verbosity for the SNMP note store.</p>
<p>For defaults see the options in <c>note_store_opt()</c>.</p>
</item>
- <marker id="ns_timeout"></marker>
- <tag><c><![CDATA[note_store_timeout() = integer() <optional>]]></c></tag>
+ <tag><marker id="ns_timeout"></marker>
+ <c><![CDATA[note_store_timeout() = integer() <optional>]]></c></tag>
<item>
<p>Note cleanup time. When storing a note in the note store,
each note is given lifetime. Every <c>timeout</c> the note_store
@@ -850,8 +852,8 @@
</item>
- <marker id="audit_trail_log"></marker>
- <tag><c><![CDATA[audit_trail_log() = [audit_trail_log_opt()] <optional>]]></c></tag>
+ <tag><marker id="audit_trail_log"></marker>
+ <c><![CDATA[audit_trail_log() = [audit_trail_log_opt()] <optional>]]></c></tag>
<item>
<p><c>audit_trail_log_opt() = {type, atl_type()} | {dir, atl_dir()} | {size, atl_size()} | {repair, atl_repair()} | {seqno, atl_seqno()}</c></p>
<p>If present, this option specifies the options for the
@@ -861,8 +863,8 @@
<p>If not present, audit trail logging is not used.</p>
</item>
- <marker id="atl_type"></marker>
- <tag><c><![CDATA[atl_type() = read | write | read_write <optional>]]></c></tag>
+ <tag><marker id="atl_type"></marker>
+ <c><![CDATA[atl_type() = read | write | read_write <optional>]]></c></tag>
<item>
<p>Specifies what type of an audit trail log should be used.
The effect of the type is actually different for the the agent
@@ -883,16 +885,16 @@
<p>Default is <c>read_write</c>.</p>
</item>
- <marker id="atl_dir"></marker>
- <tag><c><![CDATA[atl_dir = dir() <mandatory>]]></c></tag>
+ <tag><marker id="atl_dir"></marker>
+ <c><![CDATA[atl_dir = dir() <mandatory>]]></c></tag>
<item>
<p>Specifies where the audit trail log should be stored.</p>
<p>If <c>audit_trail_log</c> specifies that logging should take
place, this parameter <em>must</em> be defined.</p>
</item>
- <marker id="atl_size"></marker>
- <tag><c><![CDATA[atl_size() = {integer(), integer()} <mandatory>]]></c></tag>
+ <tag><marker id="atl_size"></marker>
+ <c><![CDATA[atl_size() = {integer(), integer()} <mandatory>]]></c></tag>
<item>
<p>Specifies the size of the audit
trail log. This parameter is sent to <c>disk_log</c>. </p>
@@ -900,8 +902,8 @@
take place, this parameter <em>must</em> be defined.</p>
</item>
- <marker id="atl_repair"></marker>
- <tag><c><![CDATA[atl_repair() = true | false | truncate | snmp_repair <optional>]]></c></tag>
+ <tag><marker id="atl_repair"></marker>
+ <c><![CDATA[atl_repair() = true | false | truncate | snmp_repair <optional>]]></c></tag>
<item>
<p>Specifies if and how the audit trail log shall be repaired
when opened. Unless this parameter has the value <c>snmp_repair</c>
@@ -913,8 +915,8 @@
<p>Default is <c>true</c>.</p>
</item>
- <marker id="atl_seqno"></marker>
- <tag><c><![CDATA[atl_seqno() = true | false <optional>]]></c></tag>
+ <tag><marker id="atl_seqno"></marker>
+ <c><![CDATA[atl_seqno() = true | false <optional>]]></c></tag>
<item>
<p>Specifies if the audit trail log entries will be (sequence)
numbered or not. The range of the sequence numbers are according
diff --git a/lib/snmp/doc/src/snmp_config.xml b/lib/snmp/doc/src/snmp_config.xml
index f10574a2a9..a085252d90 100644
--- a/lib/snmp/doc/src/snmp_config.xml
+++ b/lib/snmp/doc/src/snmp_config.xml
@@ -130,16 +130,16 @@
<marker id="agent_opts_and_types"></marker>
<p>Agent specific config options and types:</p>
<taglist>
- <marker id="agent_type"></marker>
- <tag><c><![CDATA[agent_type() = master | sub <optional>]]></c></tag>
+ <tag><marker id="agent_type"></marker>
+ <c><![CDATA[agent_type() = master | sub <optional>]]></c></tag>
<item>
<p>If <c>master</c>, one master agent is
started. Otherwise, no agents are started. </p>
<p>Default is <c>master</c>.</p>
</item>
- <marker id="agent_disco"></marker>
- <tag><c><![CDATA[agent_discovery() = [agent_discovery_opt()] <optional>]]></c></tag>
+ <tag><marker id="agent_disco"></marker>
+ <c><![CDATA[agent_discovery() = [agent_discovery_opt()] <optional>]]></c></tag>
<item>
<p><c>agent_discovery_opt() =
{terminating, agent_terminating_discovery_opts()} |
@@ -151,8 +151,8 @@
<p>For defaults see the options in <c>agent_discovery_opt()</c>.</p>
</item>
- <marker id="agent_term_disco_opts"></marker>
- <tag><c><![CDATA[agent_terminating_discovery_opts() = [agent_terminating_discovery_opt()] <optional>]]></c></tag>
+ <tag><marker id="agent_term_disco_opts"></marker>
+ <c><![CDATA[agent_terminating_discovery_opts() = [agent_terminating_discovery_opt()] <optional>]]></c></tag>
<item>
<p><c>agent_terminating_discovery_opt() =
{enable, boolean()} |
@@ -169,8 +169,8 @@
</list>
</item>
- <marker id="agent_orig_disco_opts"></marker>
- <tag><c><![CDATA[agent_originating_discovery_opts() = [agent_originating_discovery_opt()] <optional>]]></c></tag>
+ <tag><marker id="agent_orig_disco_opts"></marker>
+ <c><![CDATA[agent_originating_discovery_opts() = [agent_originating_discovery_opt()] <optional>]]></c></tag>
<item>
<p><c>agent_originating_discovery_opt() =
{enable, boolean()}</c></p>
@@ -183,38 +183,38 @@
</list>
</item>
- <marker id="agent_mt"></marker>
- <tag><c><![CDATA[multi_threaded() = bool() <optional>]]></c></tag>
+ <tag><marker id="agent_mt"></marker>
+ <c><![CDATA[multi_threaded() = bool() <optional>]]></c></tag>
<item>
<p>If <c>true</c>, the agent is multi-threaded, with one
thread for each get request. </p>
<p>Default is <c>false</c>.</p>
</item>
- <marker id="agent_data_dir"></marker>
- <tag><c><![CDATA[db_dir() = string() <mandatory>]]></c></tag>
+ <tag><marker id="agent_data_dir"></marker>
+ <c><![CDATA[db_dir() = string() <mandatory>]]></c></tag>
<item>
<p>Defines where the SNMP agent internal db files are stored.</p>
</item>
- <marker id="agent_gb_max_vbs"></marker>
- <tag><c><![CDATA[gb_max_vbs() = pos_integer() | infinity <optional>]]></c></tag>
+ <tag><marker id="agent_gb_max_vbs"></marker>
+ <c><![CDATA[gb_max_vbs() = pos_integer() | infinity <optional>]]></c></tag>
<item>
<p>Defines the maximum number of varbinds allowed
in a Get-BULK response.</p>
<p>Default is <c>1000</c>.</p>
</item>
- <marker id="agent_local_db"></marker>
- <tag><c><![CDATA[local_db() = [local_db_opt()] <optional>]]></c></tag>
+ <tag><marker id="agent_local_db"></marker>
+ <c><![CDATA[local_db() = [local_db_opt()] <optional>]]></c></tag>
<item>
<p><c>local_db_opt() = {repair, agent_repair()} | {auto_save, agent_auto_save()} | {verbosity, verbosity()}</c></p>
<p>Defines options specific for the SNMP agent local database.</p>
<p>For defaults see the options in <c>local_db_opt()</c>.</p>
</item>
- <marker id="agent_ldb_repair"></marker>
- <tag><c><![CDATA[agent_repair() = false | true | force <optional>]]></c></tag>
+ <tag><marker id="agent_ldb_repair"></marker>
+ <c><![CDATA[agent_repair() = false | true | force <optional>]]></c></tag>
<item>
<p>When starting snmpa_local_db it always tries to open an
existing database. If <c>false</c>, and some errors occur, a new
@@ -224,16 +224,16 @@
<p>Default is <c>true</c>.</p>
</item>
- <marker id="agent_ldb_auto_save"></marker>
- <tag><c><![CDATA[agent_auto_save() = integer() | infinity <optional>]]></c></tag>
+ <tag><marker id="agent_ldb_auto_save"></marker>
+ <c><![CDATA[agent_auto_save() = integer() | infinity <optional>]]></c></tag>
<item>
<p>The auto save interval. The table is flushed to disk
whenever not accessed for this amount of time.</p>
<p>Default is <c>5000</c>.</p>
</item>
- <marker id="agent_net_if"></marker>
- <tag><c><![CDATA[agent_net_if() = [agent_net_if_opt()] <optional>]]></c></tag>
+ <tag><marker id="agent_net_if"></marker>
+ <c><![CDATA[agent_net_if() = [agent_net_if_opt()] <optional>]]></c></tag>
<item>
<p><c>agent_net_if_option() = {module, agent_net_if_module()} |
{verbosity, verbosity()} |
@@ -243,8 +243,8 @@
<p>For defaults see the options in <c>agent_net_if_opt()</c>.</p>
</item>
- <marker id="agent_ni_module"></marker>
- <tag><c><![CDATA[agent_net_if_module() = atom() <optional>]]></c></tag>
+ <tag><marker id="agent_ni_module"></marker>
+ <c><![CDATA[agent_net_if_module() = atom() <optional>]]></c></tag>
<item>
<p>Module which handles the network interface part for the
SNMP agent. Must implement the
@@ -252,8 +252,8 @@
<p>Default is <c>snmpa_net_if</c>.</p>
</item>
- <marker id="agent_ni_opts"></marker>
- <tag><c><![CDATA[agent_net_if_options() = [agent_net_if_option()] <optional>]]></c></tag>
+ <tag><marker id="agent_ni_opts"></marker>
+ <c><![CDATA[agent_net_if_options() = [agent_net_if_option()] <optional>]]></c></tag>
<item>
<p><c>agent_net_if_option() = {bind_to, bind_to()} |
{sndbuf, sndbuf()} |
@@ -267,15 +267,15 @@
<p>For defaults see the options in <c>agent_net_if_option()</c>.</p>
</item>
- <marker id="agent_ni_req_limit"></marker>
- <tag><c><![CDATA[req_limit() = integer() | infinity <optional>]]></c></tag>
+ <tag><marker id="agent_ni_req_limit"></marker>
+ <c><![CDATA[req_limit() = integer() | infinity <optional>]]></c></tag>
<item>
<p>Max number of simultaneous requests handled by the agent.</p>
<p>Default is <c>infinity</c>.</p>
</item>
- <marker id="agent_ni_filter_opts"></marker>
- <tag><c><![CDATA[agent_net_if_filter_options() = [agent_net_if_filter_option()] <optional>]]></c></tag>
+ <tag><marker id="agent_ni_filter_opts"></marker>
+ <c><![CDATA[agent_net_if_filter_options() = [agent_net_if_filter_option()] <optional>]]></c></tag>
<item>
<p><c><![CDATA[agent_net_if_filter_option() = {module, agent_net_if_filter_module()}]]></c></p>
<p>These options are actually specific to the used module.
@@ -284,8 +284,8 @@
<p>For defaults see the options in <c>agent_net_if_filter_option()</c>.</p>
</item>
- <marker id="agent_ni_filter_module"></marker>
- <tag><c><![CDATA[agent_net_if_filter_module() = atom() <optional>]]></c></tag>
+ <tag><marker id="agent_ni_filter_module"></marker>
+ <c><![CDATA[agent_net_if_filter_module() = atom() <optional>]]></c></tag>
<item>
<p>Module which handles the network interface filter part for the
SNMP agent. Must implement the
@@ -294,8 +294,8 @@
<p>Default is <c>snmpa_net_if_filter</c>.</p>
</item>
- <marker id="agent_mibs"></marker>
- <tag><c><![CDATA[agent_mibs() = [string()] <optional>]]></c></tag>
+ <tag><marker id="agent_mibs"></marker>
+ <c><![CDATA[agent_mibs() = [string()] <optional>]]></c></tag>
<item>
<p>Specifies a list of MIBs (including path) that defines which MIBs
are initially loaded into the SNMP master agent. </p>
@@ -309,8 +309,8 @@
<p>Default is <c>[]</c>.</p>
</item>
- <marker id="agent_mib_storage"></marker>
- <tag><c><![CDATA[mib_storage() = [mib_storage_opt()] <optional>]]></c></tag>
+ <tag><marker id="agent_mib_storage"></marker>
+ <c><![CDATA[mib_storage() = [mib_storage_opt()] <optional>]]></c></tag>
<item>
<p><c>mib_storage_opt() = {module, mib_storage_module()} | {options, mib_storage_options()}</c></p>
<p>This option specifies how basic mib data is stored.
@@ -319,8 +319,8 @@
<p>Default is <c>[{module, snmpa_mib_storage_ets}]</c>. </p>
</item>
- <marker id="agent_mst_module"></marker>
- <tag><c><![CDATA[mib_storage_module() = snmpa_mib_data_ets | snmpa_mib_data_dets | snmpa_mib_data_mnesia | module()]]></c></tag>
+ <tag><marker id="agent_mst_module"></marker>
+ <c><![CDATA[mib_storage_module() = snmpa_mib_data_ets | snmpa_mib_data_dets | snmpa_mib_data_mnesia | module()]]></c></tag>
<item>
<p>Defines the mib storage module of the SNMP agent as defined by the
<seealso marker="snmpa_mib_storage">snmpa_mib_storage</seealso>
@@ -334,8 +334,8 @@
<p>Default module is <c>snmpa_mib_storage_ets</c>. </p>
</item>
- <marker id="agent_mst_options"></marker>
- <tag><c><![CDATA[mib_storage_options() = list() <optional>]]></c></tag>
+ <tag><marker id="agent_mst_options"></marker>
+ <c><![CDATA[mib_storage_options() = list() <optional>]]></c></tag>
<item>
<p>This is implementattion depended. That is, it depends on the
module. For each module a specific set of options are valid.
@@ -429,8 +429,8 @@
This is the old format which is "supported", but not documented,
in so far as it will be converted to the new format if found.
- <marker id="agent_mib_storage"></marker>
- <tag><c><![CDATA[mib_storage() = ets | {ets, Dir} | {ets, Dir, Action} | dets | {dets, Dir} | {dets, Dir, Action} | mnesia | {mnesia, Nodes} | {mnesia, Nodes, Action} <optional>]]></c></tag>
+ <tag><marker id="agent_mib_storage"></marker>
+ <c><![CDATA[mib_storage() = ets | {ets, Dir} | {ets, Dir, Action} | dets | {dets, Dir} | {dets, Dir, Action} | mnesia | {mnesia, Nodes} | {mnesia, Nodes, Action} <optional>]]></c></tag>
<item>
<p>Specifies how info retrieved from the mibs will be stored.</p>
<p>If <c>mib_storage</c> is <c>{ets, Dir}</c>, the table will also be
@@ -456,16 +456,16 @@ in so far as it will be converted to the new format if found.
</item>
-->
- <marker id="agent_mib_server"></marker>
- <tag><c><![CDATA[mib_server() = [mib_server_opt()] <optional>]]></c></tag>
+ <tag><marker id="agent_mib_server"></marker>
+ <c><![CDATA[mib_server() = [mib_server_opt()] <optional>]]></c></tag>
<item>
<p><c>mib_server_opt() = {mibentry_override, mibentry_override()} | {trapentry_override, trapentry_override()} | {verbosity, verbosity()} | {cache, mibs_cache()} | {data_module, mib_server_data_module()}</c></p>
<p>Defines options specific for the SNMP agent mib server. </p>
<p>For defaults see the options in <c>mib_server_opt()</c>.</p>
</item>
- <marker id="agent_ms_meo"></marker>
- <tag><c><![CDATA[mibentry_override() = bool() <optional>]]></c></tag>
+ <tag><marker id="agent_ms_meo"></marker>
+ <c><![CDATA[mibentry_override() = bool() <optional>]]></c></tag>
<item>
<p>If this value is false, then when loading a mib each mib-
entry is checked prior to installation of the mib.
@@ -474,8 +474,8 @@ in so far as it will be converted to the new format if found.
<p>Default is <c>false</c>.</p>
</item>
- <marker id="agent_ms_teo"></marker>
- <tag><c><![CDATA[trapentry_override() = bool() <optional>]]></c></tag>
+ <tag><marker id="agent_ms_teo"></marker>
+ <c><![CDATA[trapentry_override() = bool() <optional>]]></c></tag>
<item>
<p>If this value is false, then when loading a mib each trap
is checked prior to installation of the mib.
@@ -484,11 +484,13 @@ in so far as it will be converted to the new format if found.
<p>Default is <c>false</c>.</p>
</item>
- <marker id="agent_ms_data_module"></marker>
+
<!--
- <tag><c><![CDATA[mib_server_data_module() = snmpa_mib_data_tttn | snmpa_mib_data_ttln | module() <optional>]]></c></tag>
+ <tag><marker id="agent_ms_data_module"></marker>
+ <c><![CDATA[mib_server_data_module() = snmpa_mib_data_tttn | snmpa_mib_data_ttln | module() <optional>]]></c></tag>
-->
- <tag><c><![CDATA[mib_server_data_module() = snmpa_mib_data_tttn | module() <optional>]]></c></tag>
+ <tag><marker id="agent_ms_data_module"></marker>
+ <c><![CDATA[mib_server_data_module() = snmpa_mib_data_tttn | module() <optional>]]></c></tag>
<item>
<p>Defines the backend data module of the SNMP agent mib-server as
defined by the
@@ -505,24 +507,24 @@ in so far as it will be converted to the new format if found.
<p>Default module is <c>snmpa_mib_data_tttn</c>. </p>
</item>
- <marker id="agent_ms_cache"></marker>
- <tag><c><![CDATA[mibs_cache() = bool() | mibs_cache_opts() <optional>]]></c></tag>
+ <tag><marker id="agent_ms_cache"></marker>
+ <c><![CDATA[mibs_cache() = bool() | mibs_cache_opts() <optional>]]></c></tag>
<item>
<p>Shall the agent utilize the mib server lookup cache or not.</p>
<p>Default is <c>true</c> (in which case the <c>mibs_cache_opts()</c>
default values apply).</p>
</item>
- <marker id="agent_ms_cache_opts"></marker>
- <tag><c><![CDATA[mibs_cache_opts() = [mibs_cache_opt()] <optional>]]></c></tag>
+ <tag><marker id="agent_ms_cache_opts"></marker>
+ <c><![CDATA[mibs_cache_opts() = [mibs_cache_opt()] <optional>]]></c></tag>
<item>
<p><c>mibs_cache_opt() = {autogc, mibs_cache_autogc()} | {gclimit, mibs_cache_gclimit()} | {age, mibs_cache_age()}</c></p>
<p>Defines options specific for the SNMP agent mib server cache. </p>
<p>For defaults see the options in <c>mibs_cache_opt()</c>.</p>
</item>
- <marker id="agent_ms_cache_autogc"></marker>
- <tag><c><![CDATA[mibs_cache_autogc() = bool() <optional>]]></c></tag>
+ <tag><marker id="agent_ms_cache_autogc"></marker>
+ <c><![CDATA[mibs_cache_autogc() = bool() <optional>]]></c></tag>
<item>
<p>Defines if the mib server shall perform cache gc automatically or
leave it to the user (see
@@ -530,8 +532,8 @@ in so far as it will be converted to the new format if found.
<p>Default is <c>true</c>.</p>
</item>
- <marker id="agent_ms_cache_age"></marker>
- <tag><c><![CDATA[mibs_cache_age() = integer() > 0 <optional>]]></c></tag>
+ <tag><marker id="agent_ms_cache_age"></marker>
+ <c><![CDATA[mibs_cache_age() = integer() > 0 <optional>]]></c></tag>
<item>
<p>Defines how old the entries in the cache will be allowed
to become before they are GC'ed (assuming GC is performed).
@@ -540,8 +542,8 @@ in so far as it will be converted to the new format if found.
<p>Default is <c>10 timutes</c>.</p>
</item>
- <marker id="agent_ms_cache_gclimit"></marker>
- <tag><c><![CDATA[mibs_cache_gclimit() = integer() > 0 | infinity <optional>]]></c></tag>
+ <tag><marker id="agent_ms_cache_gclimit"></marker>
+ <c><![CDATA[mibs_cache_gclimit() = integer() > 0 | infinity <optional>]]></c></tag>
<item>
<p>When performing a GC, this is the max number of cache entries
that will be deleted from the cache. </p>
@@ -551,8 +553,8 @@ in so far as it will be converted to the new format if found.
<p>Default is <c>100</c>.</p>
</item>
- <marker id="agent_error_report_mod"></marker>
- <tag><c><![CDATA[error_report_mod() = atom() <optional>]]></c></tag>
+ <tag><marker id="agent_error_report_mod"></marker>
+ <c><![CDATA[error_report_mod() = atom() <optional>]]></c></tag>
<item>
<p>Defines an error report module, implementing the
<seealso marker="snmpa_error_report">snmpa_error_report</seealso>
@@ -561,38 +563,38 @@ in so far as it will be converted to the new format if found.
<p>Default is <c>snmpa_error_logger</c>.</p>
</item>
- <marker id="agent_symbolic_store"></marker>
- <tag><c>symbolic_store() = [symbolic_store_opt()]</c></tag>
+ <tag><marker id="agent_symbolic_store"></marker>
+ <c>symbolic_store() = [symbolic_store_opt()]</c></tag>
<item>
<p><c>symbolic_store_opt() = {verbosity, verbosity()}</c></p>
<p>Defines options specific for the SNMP agent symbolic store. </p>
<p>For defaults see the options in <c>symbolic_store_opt()</c>.</p>
</item>
- <marker id="agent_target_cache"></marker>
- <tag><c>target_cache() = [target_cache_opt()]</c></tag>
+ <tag><marker id="agent_target_cache"></marker>
+ <c>target_cache() = [target_cache_opt()]</c></tag>
<item>
<p><c>target_cache_opt() = {verbosity, verbosity()}</c></p>
<p>Defines options specific for the SNMP agent target cache. </p>
<p>For defaults see the options in <c>target_cache_opt()</c>.</p>
</item>
- <marker id="agent_config"></marker>
- <tag><c><![CDATA[agent_config() = [agent_config_opt()] <mandatory>]]></c></tag>
+ <tag><marker id="agent_config"></marker>
+ <c><![CDATA[agent_config() = [agent_config_opt()] <mandatory>]]></c></tag>
<item>
<p><c>agent_config_opt() = {dir, agent_config_dir()} | {force_load, force_load()} | {verbosity, verbosity()}</c></p>
<p>Defines specific config related options for the SNMP agent. </p>
<p>For defaults see the options in <c>agent_config_opt()</c>.</p>
</item>
- <marker id="agent_config_dir"></marker>
- <tag><c><![CDATA[agent_config_dir = dir() <mandatory>]]></c></tag>
+ <tag><marker id="agent_config_dir"></marker>
+ <c><![CDATA[agent_config_dir = dir() <mandatory>]]></c></tag>
<item>
<p>Defines where the SNMP agent configuration files are stored.</p>
</item>
- <marker id="agent_force_load"></marker>
- <tag><c><![CDATA[force_load() = bool() <optional>]]></c></tag>
+ <tag><marker id="agent_force_load"></marker>
+ <c><![CDATA[force_load() = bool() <optional>]]></c></tag>
<item>
<p>If <c>true</c> the configuration files are re-read
during start-up, and the contents of the configuration
@@ -606,16 +608,16 @@ in so far as it will be converted to the new format if found.
<marker id="manager_opts_and_types"></marker>
<p>Manager specific config options and types:</p>
<taglist>
- <marker id="manager_server"></marker>
- <tag><c><![CDATA[server() = [server_opt()] <optional>]]></c></tag>
+ <tag><marker id="manager_server"></marker>
+ <c><![CDATA[server() = [server_opt()] <optional>]]></c></tag>
<item>
<p><c>server_opt() = {timeout, server_timeout()} | {verbosity, verbosity()}</c></p>
<p>Specifies the options for the manager server process.</p>
<p>Default is <c>silence</c>.</p>
</item>
- <marker id="manager_server_timeout"></marker>
- <tag><c><![CDATA[server_timeout() = integer() <optional>]]></c></tag>
+ <tag><marker id="manager_server_timeout"></marker>
+ <c><![CDATA[server_timeout() = integer() <optional>]]></c></tag>
<item>
<p>Asynchronous request cleanup time. For every requests,
some info is stored internally, in order to be able to
@@ -635,44 +637,44 @@ in so far as it will be converted to the new format if found.
<p>Default is <c>30000</c>.</p>
</item>
- <marker id="manager_config"></marker>
- <tag><c><![CDATA[manager_config() = [manager_config_opt()] <mandatory>]]></c></tag>
+ <tag><marker id="manager_config"></marker>
+ <c><![CDATA[manager_config() = [manager_config_opt()] <mandatory>]]></c></tag>
<item>
<p><c>manager_config_opt() = {dir, manager_config_dir()} | {db_dir, manager_db_dir()} | {db_init_error, db_init_error()} | {repair, manager_repair()} | {auto_save, manager_auto_save()} | {verbosity, verbosity()}</c></p>
<p>Defines specific config related options for the SNMP manager. </p>
<p>For defaults see the options in <c>manager_config_opt()</c>.</p>
</item>
- <marker id="manager_config_dir"></marker>
- <tag><c><![CDATA[manager_config_dir = dir() <mandatory>]]></c></tag>
+ <tag><marker id="manager_config_dir"></marker>
+ <c><![CDATA[manager_config_dir = dir() <mandatory>]]></c></tag>
<item>
<p>Defines where the SNMP manager configuration files are stored.</p>
</item>
- <marker id="manager_config_db_dir"></marker>
- <tag><c><![CDATA[manager_db_dir = dir() <mandatory>]]></c></tag>
+ <tag><marker id="manager_config_db_dir"></marker>
+ <c><![CDATA[manager_db_dir = dir() <mandatory>]]></c></tag>
<item>
<p>Defines where the SNMP manager store persistent data.</p>
</item>
- <marker id="manager_config_repair"></marker>
- <tag><c><![CDATA[manager_repair() = false | true | force <optional>]]></c></tag>
+ <tag><marker id="manager_config_repair"></marker>
+ <c><![CDATA[manager_repair() = false | true | force <optional>]]></c></tag>
<item>
<p>Defines the repair option for the persistent database (if
and how the table is repaired when opened). </p>
<p>Default is <c>true</c>.</p>
</item>
- <marker id="manager_config_auto_save"></marker>
- <tag><c><![CDATA[manager_auto_save() = integer() | infinity <optional>]]></c></tag>
+ <tag><marker id="manager_config_auto_save"></marker>
+ <c><![CDATA[manager_auto_save() = integer() | infinity <optional>]]></c></tag>
<item>
<p>The auto save interval. The table is flushed to disk
whenever not accessed for this amount of time.</p>
<p>Default is <c>5000</c>.</p>
</item>
- <marker id="manager_irb"></marker>
- <tag><c><![CDATA[manager_irb() = auto | user | {user, integer()} <optional>]]></c></tag>
+ <tag><marker id="manager_irb"></marker>
+ <c><![CDATA[manager_irb() = auto | user | {user, integer()} <optional>]]></c></tag>
<item>
<p>This option defines how the manager will handle the sending of
response (acknowledgment) to received inform-requests. </p>
@@ -701,16 +703,16 @@ in so far as it will be converted to the new format if found.
<p>Default is <c>auto</c>.</p>
</item>
- <marker id="manager_mibs"></marker>
- <tag><c><![CDATA[manager_mibs() = [string()] <optional>]]></c></tag>
+ <tag><marker id="manager_mibs"></marker>
+ <c><![CDATA[manager_mibs() = [string()] <optional>]]></c></tag>
<item>
<p>Specifies a list of MIBs (including path) and defines which MIBs
are initially loaded into the SNMP manager. </p>
<p>Default is <c>[]</c>.</p>
</item>
- <marker id="manager_net_if"></marker>
- <tag><c><![CDATA[manager_net_if() = [manager_net_if_opt()] <optional>]]></c></tag>
+ <tag><marker id="manager_net_if"></marker>
+ <c><![CDATA[manager_net_if() = [manager_net_if_opt()] <optional>]]></c></tag>
<item>
<p><c>manager_net_if_opt() = {module, manager_net_if_module()} |
{verbosity, verbosity()} |
@@ -720,8 +722,8 @@ in so far as it will be converted to the new format if found.
<p>For defaults see the options in <c>manager_net_if_opt()</c>.</p>
</item>
- <marker id="manager_ni_opts"></marker>
- <tag><c><![CDATA[manager_net_if_options() = [manager_net_if_option()] <optional>]]></c></tag>
+ <tag><marker id="manager_ni_opts"></marker>
+ <c><![CDATA[manager_net_if_options() = [manager_net_if_option()] <optional>]]></c></tag>
<item>
<p><c>manager_net_if_option() = {bind_to, bind_to()} |
{sndbuf, sndbuf()} |
@@ -734,8 +736,8 @@ in so far as it will be converted to the new format if found.
<p>For defaults see the options in <c>manager_net_if_option()</c>.</p>
</item>
- <marker id="manager_ni_module"></marker>
- <tag><c><![CDATA[manager_net_if_module() = atom() <optional>]]></c></tag>
+ <tag><marker id="manager_ni_module"></marker>
+ <c><![CDATA[manager_net_if_module() = atom() <optional>]]></c></tag>
<item>
<p>The module which handles the network interface part for the
SNMP manager. It must implement the
@@ -743,8 +745,8 @@ in so far as it will be converted to the new format if found.
<p>Default is <c>snmpm_net_if</c>. </p>
</item>
- <marker id="manager_ni_filter_opts"></marker>
- <tag><c><![CDATA[manager_net_if_filter_options() = [manager_net_if_filter_option()] <optional>]]></c></tag>
+ <tag><marker id="manager_ni_filter_opts"></marker>
+ <c><![CDATA[manager_net_if_filter_options() = [manager_net_if_filter_option()] <optional>]]></c></tag>
<item>
<p><c>manager_net_if_filter_option() = {module, manager_net_if_filter_module()}</c></p>
<p>These options are actually specific to the used module.
@@ -754,8 +756,8 @@ in so far as it will be converted to the new format if found.
<c>manager_net_if_filter_option()</c>.</p>
</item>
- <marker id="manager_ni_filter_module"></marker>
- <tag><c><![CDATA[manager_net_if_filter_module() = atom() <optional>]]></c></tag>
+ <tag><marker id="manager_ni_filter_module"></marker>
+ <c><![CDATA[manager_net_if_filter_module() = atom() <optional>]]></c></tag>
<item>
<p>Module which handles the network interface filter part for the
SNMP manager. Must implement the
@@ -763,16 +765,16 @@ in so far as it will be converted to the new format if found.
<p>Default is <c>snmpm_net_if_filter</c>.</p>
</item>
- <marker id="manager_def_user_module"></marker>
- <tag><c><![CDATA[def_user_module() = atom() <optional>]]></c></tag>
+ <tag><marker id="manager_def_user_module"></marker>
+ <c><![CDATA[def_user_module() = atom() <optional>]]></c></tag>
<item>
<p>The module implementing the default user. See the
<seealso marker="snmpm_user">snmpm_user</seealso> behaviour.</p>
<p>Default is <c>snmpm_user_default</c>.</p>
</item>
- <marker id="manager_def_user_data"></marker>
- <tag><c><![CDATA[def_user_data() = term() <optional>]]></c></tag>
+ <tag><marker id="manager_def_user_data"></marker>
+ <c><![CDATA[def_user_data() = term() <optional>]]></c></tag>
<item>
<p>Data for the default user. Passed to the user when calling
the callback functions.</p>
@@ -783,8 +785,8 @@ in so far as it will be converted to the new format if found.
<marker id="common_types"></marker>
<p>Common config types:</p>
<taglist>
- <marker id="restart_type"></marker>
- <tag><c>restart_type() = permanent | transient | temporary</c></tag>
+ <tag><marker id="restart_type"></marker>
+ <c>restart_type() = permanent | transient | temporary</c></tag>
<item>
<p>See <seealso marker="stdlib:supervisor#child_spec">supervisor</seealso>
documentation for more info.</p>
@@ -792,8 +794,8 @@ in so far as it will be converted to the new format if found.
for the manager.</p>
</item>
- <marker id="db_init_error"></marker>
- <tag><c>db_init_error() = terminate | create | create_db_and_dir</c></tag>
+ <tag><marker id="db_init_error"></marker>
+ <c>db_init_error() = terminate | create | create_db_and_dir</c></tag>
<item>
<p>Defines what to do if the agent is unable to open an
existing database file. <c>terminate</c> means that the
@@ -805,31 +807,31 @@ in so far as it will be converted to the new format if found.
<p>Default is <c>terminate</c>.</p>
</item>
- <marker id="prio"></marker>
- <tag><c><![CDATA[priority() = atom() <optional>]]></c></tag>
+ <tag><marker id="prio"></marker>
+ <c><![CDATA[priority() = atom() <optional>]]></c></tag>
<item>
<p>Defines the Erlang priority for all SNMP processes.</p>
<p>Default is <c>normal</c>.</p>
</item>
- <marker id="versions"></marker>
- <tag><c><![CDATA[versions() = [version()] <optional>]]></c></tag>
+ <tag><marker id="versions"></marker>
+ <c><![CDATA[versions() = [version()] <optional>]]></c></tag>
<item>
<p><c>version() = v1 | v2 | v3</c></p>
<p>Which SNMP versions shall be accepted/used.</p>
<p>Default is <c>[v1,v2,v3]</c>.</p>
</item>
- <marker id="verbosity"></marker>
- <tag><c><![CDATA[verbosity() = silence | info | log | debug | trace <optional>]]></c></tag>
+ <tag><marker id="verbosity"></marker>
+ <c><![CDATA[verbosity() = silence | info | log | debug | trace <optional>]]></c></tag>
<item>
<p>Verbosity for a SNMP process. This specifies now much debug info
is printed.</p>
<p>Default is <c>silence</c>.</p>
</item>
- <marker id="bind_to"></marker>
- <tag><c><![CDATA[bind_to() = bool() <optional>]]></c></tag>
+ <tag><marker id="bind_to"></marker>
+ <c><![CDATA[bind_to() = bool() <optional>]]></c></tag>
<item>
<p>If <c>true</c>, net_if binds to the IP address.
If <c>false</c>, net_if listens on any IP address on the host
@@ -837,8 +839,8 @@ in so far as it will be converted to the new format if found.
<p>Default is <c>false</c>.</p>
</item>
- <marker id="no_reuse"></marker>
- <tag><c><![CDATA[no_reuse() = bool() <optional>]]></c></tag>
+ <tag><marker id="no_reuse"></marker>
+ <c><![CDATA[no_reuse() = bool() <optional>]]></c></tag>
<item>
<p>If <c>true</c>, net_if does not specify that the IP
and port address should be reusable. If <c>false</c>,
@@ -846,30 +848,30 @@ in so far as it will be converted to the new format if found.
<p>Default is <c>false</c>.</p>
</item>
- <marker id="recbuf"></marker>
- <tag><c><![CDATA[recbuf() = integer() <optional>]]></c></tag>
+ <tag><marker id="recbuf"></marker>
+ <c><![CDATA[recbuf() = integer() <optional>]]></c></tag>
<item>
<p>Receive buffer size. </p>
<p>Default value is defined by <c>gen_udp</c>.</p>
</item>
- <marker id="sndbuf"></marker>
- <tag><c><![CDATA[sndbuf() = integer() <optional>]]></c></tag>
+ <tag><marker id="sndbuf"></marker>
+ <c><![CDATA[sndbuf() = integer() <optional>]]></c></tag>
<item>
<p>Send buffer size. </p>
<p>Default value is defined by <c>gen_udp</c>.</p>
</item>
- <marker id="note_store"></marker>
- <tag><c><![CDATA[note_store() = [note_store_opt()] <optional>]]></c></tag>
+ <tag><marker id="note_store"></marker>
+ <c><![CDATA[note_store() = [note_store_opt()] <optional>]]></c></tag>
<item>
<p><c>note_store_opt() = {timeout, note_store_timeout()} | {verbosity, verbosity()}</c></p>
<p>Specifies the options for the SNMP note store.</p>
<p>For defaults see the options in <c>note_store_opt()</c>.</p>
</item>
- <marker id="ns_timeout"></marker>
- <tag><c><![CDATA[note_store_timeout() = integer() <optional>]]></c></tag>
+ <tag><marker id="ns_timeout"></marker>
+ <c><![CDATA[note_store_timeout() = integer() <optional>]]></c></tag>
<item>
<p>Note cleanup time. When storing a note in the note store,
each note is given lifetime. Every <c>timeout</c> the note_store
@@ -878,8 +880,8 @@ in so far as it will be converted to the new format if found.
<p>Default is <c>30000</c>.</p>
</item>
- <marker id="audit_trail_log"></marker>
- <tag><c><![CDATA[audit_trail_log() [audit_trail_log_opt()] <optional>]]></c></tag>
+ <tag><marker id="audit_trail_log"></marker>
+ <c><![CDATA[audit_trail_log() [audit_trail_log_opt()] <optional>]]></c></tag>
<item>
<p><c>audit_trail_log_opt() = {type, atl_type()} | {dir, atl_dir()} | {size, atl_size()} | {repair, atl_repair()} | {seqno, atl_seqno()}</c></p>
<p>If present, this option specifies the options for the
@@ -889,8 +891,8 @@ in so far as it will be converted to the new format if found.
<p>If not present, audit trail logging is not used.</p>
</item>
- <marker id="atl_type"></marker>
- <tag><c><![CDATA[atl_type() = read | write | read_write <optional>]]></c></tag>
+ <tag><marker id="atl_type"></marker>
+ <c><![CDATA[atl_type() = read | write | read_write <optional>]]></c></tag>
<item>
<p>Specifies what type of an audit trail log should be used.
The effect of the type is actually different for the the agent
@@ -911,16 +913,16 @@ in so far as it will be converted to the new format if found.
<p>Default is <c>read_write</c>.</p>
</item>
- <marker id="atl_dir"></marker>
- <tag><c><![CDATA[atl_dir = dir() <mandatory>]]></c></tag>
+ <tag><marker id="atl_dir"></marker>
+ <c><![CDATA[atl_dir = dir() <mandatory>]]></c></tag>
<item>
<p>Specifies where the audit trail log should be stored.</p>
<p>If <c>audit_trail_log</c> specifies that logging should take
place, this parameter <em>must</em> be defined.</p>
</item>
- <marker id="atl_size"></marker>
- <tag><c><![CDATA[atl_size() = {integer(), integer()} <mandatory>]]></c></tag>
+ <tag><marker id="atl_size"></marker>
+ <c><![CDATA[atl_size() = {integer(), integer()} <mandatory>]]></c></tag>
<item>
<p>Specifies the size of the audit
trail log. This parameter is sent to <c>disk_log</c>. </p>
@@ -928,8 +930,8 @@ in so far as it will be converted to the new format if found.
take place, this parameter <em>must</em> be defined.</p>
</item>
- <marker id="atl_repair"></marker>
- <tag><c><![CDATA[atl_repair() = true | false | truncate | snmp_repair <optional>]]></c></tag>
+ <tag><marker id="atl_repair"></marker>
+ <c><![CDATA[atl_repair() = true | false | truncate | snmp_repair <optional>]]></c></tag>
<item>
<p>Specifies if and how the audit trail log shall be repaired
when opened. Unless this parameter has the value <c>snmp_repair</c>
@@ -941,8 +943,8 @@ in so far as it will be converted to the new format if found.
<p>Default is <c>true</c>.</p>
</item>
- <marker id="atl_seqno"></marker>
- <tag><c><![CDATA[atl_seqno() = true | false <optional>]]></c></tag>
+ <tag><marker id="atl_seqno"></marker>
+ <c><![CDATA[atl_seqno() = true | false <optional>]]></c></tag>
<item>
<p>Specifies if the audit trail log entries will be (sequence)
numbered or not. The range of the sequence numbers are according
diff --git a/lib/snmp/doc/src/snmp_manager_netif.xml b/lib/snmp/doc/src/snmp_manager_netif.xml
index 8454d03b17..98d4e7fd96 100644
--- a/lib/snmp/doc/src/snmp_manager_netif.xml
+++ b/lib/snmp/doc/src/snmp_manager_netif.xml
@@ -75,8 +75,7 @@
<p>In this section a <c>Domain</c> field is the transport domain i.e
one of <c>transportDomainUdpIpv4</c> or <c>transportDomainUdpIpv6</c>,
and an <c>Addr</c> field is an
- <c>{<seealso marker="kernel:inet#type-ip_address">IpAddr</seealso>,
- IpPort}</c> tuple.</p>
+ <c>{</c><seealso marker="kernel:inet#type-ip_address"><c>IpAddr</c></seealso><c>,IpPort}</c> tuple.</p>
<p>Net if must send the following message when it receives an
SNMP PDU from the network that is aimed for the MasterAgent:
diff --git a/lib/snmp/doc/src/snmpa.xml b/lib/snmp/doc/src/snmpa.xml
index f205af6e88..c84eeec524 100644
--- a/lib/snmp/doc/src/snmpa.xml
+++ b/lib/snmp/doc/src/snmpa.xml
@@ -622,12 +622,12 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
<p>Converts an Audit Trail Log to a readable format and
prints it on stdio.
<c>LogName</c> defaults to "snmpa_log".
- <c>LogFile</c> defaults to "snmpa.log".
+ <c>LogFile</c> defaults to "snmpa.log".</p>
<p>The <c>Block</c> option indicates if the log should be blocked
during conversion. This could be usefull when converting large
logs (when otherwise the log could wrap during conversion).
Defaults to <c>true</c>. </p>
- See <seealso marker="snmp#log_to_io">snmp:log_to_io</seealso>
+ <p>See <seealso marker="snmp#log_to_io">snmp:log_to_io</seealso>
for more info.</p>
<marker id="change_log_size"></marker>
diff --git a/lib/snmp/doc/src/snmpm.xml b/lib/snmp/doc/src/snmpm.xml
index b14c0e6afd..ab288fd020 100644
--- a/lib/snmp/doc/src/snmpm.xml
+++ b/lib/snmp/doc/src/snmpm.xml
@@ -1241,12 +1241,12 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
<p>Converts an Audit Trail Log to a readable text file.
<c>OutFile</c> defaults to "./snmpm_log.txt".
<c>LogName</c> defaults to "snmpm_log".
- <c>LogFile</c> defaults to "snmpm.log".
+ <c>LogFile</c> defaults to "snmpm.log".</p>
<p>The <c>Block</c> argument indicates if the log should be blocked
during conversion. This could be usefull when converting large
logs (when otherwise the log could wrap during conversion).
Defaults to <c>true</c>. </p>
- See <seealso marker="snmp#log_to_txt">snmp:log_to_txt</seealso>
+ <p>See <seealso marker="snmp#log_to_txt">snmp:log_to_txt</seealso>
for more info.</p>
<marker id="log_to_io"></marker>
@@ -1280,12 +1280,12 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
<p>Converts an Audit Trail Log to a readable format and
prints it on stdio.
<c>LogName</c> defaults to "snmpm_log".
- <c>LogFile</c> defaults to "snmpm.log".
+ <c>LogFile</c> defaults to "snmpm.log".</p>
<p>The <c>Block</c> argument indicates if the log should be blocked
during conversion. This could be usefull when converting large
logs (when otherwise the log could wrap during conversion).
Defaults to <c>true</c>. </p>
- See <seealso marker="snmp#log_to_io">snmp:log_to_io</seealso>
+ <p>See <seealso marker="snmp#log_to_io">snmp:log_to_io</seealso>
for more info.</p>
<marker id="change_log_size"></marker>
diff --git a/lib/snmp/src/app/snmp.appup.src b/lib/snmp/src/app/snmp.appup.src
index 6632d29457..77418f920f 100644
--- a/lib/snmp/src/app/snmp.appup.src
+++ b/lib/snmp/src/app/snmp.appup.src
@@ -29,6 +29,7 @@
%% {update, snmpa_local_db, soft, soft_purge, soft_purge, []}
%% {add_module, snmpm_net_if_mt}
[
+ {"5.2", [{load_module, snmp_conf, soft_purge, soft_purge, []}]},
{"5.1.2", [ % Only runtime dependencies change
]},
{"5.1.1", [{restart_application, snmp}]},
@@ -50,6 +51,7 @@
%% {remove, {snmpm_net_if_mt, soft_purge, soft_purge}}
[
+ {"5.2", [{load_module, snmp_conf, soft_purge, soft_purge, []}]},
{"5.1.2", [ % Only runtime dependencies change
]},
{"5.1.1", [{restart_application, snmp}]},
diff --git a/lib/snmp/src/misc/snmp_conf.erl b/lib/snmp/src/misc/snmp_conf.erl
index 0364613f8e..6264d79cec 100644
--- a/lib/snmp/src/misc/snmp_conf.erl
+++ b/lib/snmp/src/misc/snmp_conf.erl
@@ -1005,6 +1005,8 @@ check_imask(IMask) when is_list(IMask) ->
do_check_imask(IMask),
{ok, IMask}.
+do_check_imask([]) ->
+ ok;
do_check_imask([0|IMask]) ->
do_check_imask(IMask);
do_check_imask([1|IMask]) ->
diff --git a/lib/ssh/doc/src/notes.xml b/lib/ssh/doc/src/notes.xml
index bb111c8e0e..010b1b15c7 100644
--- a/lib/ssh/doc/src/notes.xml
+++ b/lib/ssh/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2014</year>
+ <year>2004</year><year>2015</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -30,6 +30,22 @@
<file>notes.xml</file>
</header>
+<section><title>Ssh 4.1.3</title>
+
+ <section><title>Known Bugs and Problems</title>
+ <list>
+ <item>
+ <p>
+ SSH_MSG_KEX_DH_GEX_REQUEST_OLD implemented to make PuTTY
+ work with erl server.</p>
+ <p>
+ Own Id: OTP-13140</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Ssh 4.1.2</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -216,9 +232,9 @@
<p>
Thanks to Simon Cornish</p>
<p>
- Own Id: OTP-12760 Aux Id: <a
+ Own Id: OTP-12760 Aux Id: <url
href="https://github.com/erlang/otp/pull/715">pull req
- 715</a> </p>
+ 715</url> </p>
</item>
<item>
<p>
@@ -384,13 +400,13 @@
</item>
<item>
<p>
- Made Codenomicon Defensics test suite pass: <list>
+ Made Codenomicon Defensics test suite pass:</p> <list>
<item>limit number of algorithms in kexinit
message</item> <item>check 'e' and 'f' parameters in
kexdh</item> <item>implement 'keyboard-interactive' user
authentication on server side</item> <item> return plain
text message to bad version exchange message</item>
- </list></p>
+ </list>
<p>
Own Id: OTP-12784</p>
</item>
diff --git a/lib/ssh/doc/src/ssh.xml b/lib/ssh/doc/src/ssh.xml
index 0e5a0706f5..850557444d 100644
--- a/lib/ssh/doc/src/ssh.xml
+++ b/lib/ssh/doc/src/ssh.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2004</year><year>2014</year>
+ <year>2004</year><year>2015</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -32,34 +32,10 @@
<modulesummary>Main API of the ssh application</modulesummary>
<description>
<p>Interface module for the <c>ssh</c> application.</p>
+ <p>See <seealso marker="ssh:SSH_app#supported">ssh(6)</seealso> for details of supported version,
+ algorithms and unicode support.</p>
</description>
- <section>
- <title>SSH</title>
- <marker id="supported"/>
- <list type="bulleted">
- <item>For application dependencies see <seealso marker="SSH_app"> ssh(6)</seealso> </item>
- <item>Supported SSH version is 2.0.</item>
- <item>Supported public key algorithms: ecdsa-sha2-nistp256, ecdsa-sha2-nistp384, ecdsa-sha2-nistp521, ssh-rsa and ssh-dss.</item>
- <item>Supported MAC algorithms: hmac-sha2-256, hmac-sha2-512 and hmac-sha1.</item>
- <item>Supported encryption algorithms: aes256-ctr, aes192-ctr, aes128-ctr, aes128-cb and 3des-cbc.</item>
- <item>Supported key exchange algorithms: ecdh-sha2-nistp256, ecdh-sha2-nistp384, ecdh-sha2-nistp521, diffie-hellman-group14-sha1, diffie-hellman-group-exchange-sha1, diffie-hellman-group-exchange-sha256 and diffie-hellman-group1-sha1</item>
- <item>Supported compression algorithms: none, [email protected] and zlib</item>
- <item>Supports unicode filenames if the emulator and the underlaying OS support it.
- See section DESCRIPTION in the
- <seealso marker="kernel:file">file</seealso> manual page in <c>kernel</c>
- for information about this subject.</item>
- <item>Supports unicode in shell and CLI.</item>
- </list>
- <p>The actual set of algorithms can vary depending on which OpenSSL crypto library that is installed on the machine.
- For the list on a particular installation, use the command <seealso marker="#default_algorithms/0">default_algorithms/0</seealso>.
- The user may override the default algorithm configuration both on the server side and the client side.
- See the option preferred_algorithms in the <seealso marker="#daemon/1">daemon</seealso> and
- <seealso marker="#connect/3">connect</seealso> functions.
-</p>
-
- </section>
-
<section>
<title>OPTIONS</title>
<p>The exact behaviour of some functions can be adjusted with the use of options which are documented together
@@ -109,6 +85,15 @@
<item><p><c>atom()</c> - Name of the Erlang module
implementing the subsystem using the <c>ssh_channel</c> behavior, see
<seealso marker="ssh_channel">ssh_channel(3)</seealso></p></item>
+ <tag><c>key_cb() =</c></tag>
+ <item>
+ <p><c>atom() | {atom(), list()}</c></p>
+ <p><c>atom()</c> - Name of the erlang module implementing the behaviours
+ <seealso marker="ssh_client_key_api">ssh_client_key_api</seealso> or
+ <seealso marker="ssh_client_key_api">ssh_client_key_api</seealso> as the
+ case maybe.</p>
+ <p><c>list()</c> - List of options that can be passed to the callback module.</p>
+ </item>
<tag><c>channel_init_args() =</c></tag>
<item><p><c>list()</c></p></item>
@@ -221,26 +206,25 @@
<tag><c><![CDATA[{public_key_alg, 'ssh-rsa' | 'ssh-dss'}]]></c></tag>
<item>
<note>
- <p>This option is kept for compatibility. It is ignored if the <c>preferred_algorithms</c>
- option is used. The equivalence of <c>{public_key_alg,'ssh-dss'}</c> is
- <c>{preferred_algorithms, [{public_key,['ssh-dss','ssh-rsa']}]}</c>.</p>
+ <p>This option will be removed in OTP 20, but is kept for compatibility. It is ignored if
+ the preferred <c>pref_public_key_algs</c> option is used.</p>
</note>
<p>Sets the preferred public key algorithm to use for user
authentication. If the preferred algorithm fails,
- the other algorithm is tried. The default is
- to try <c><![CDATA['ssh-rsa']]></c> first.</p>
+ the other algorithm is tried. If <c>{public_key_alg, 'ssh-rsa'}</c> is set, it is translated
+ to <c>{pref_public_key_algs, ['ssh-rsa','ssh-dss']}</c>. If it is
+ <c>{public_key_alg, 'ssh-dss'}</c>, it is translated
+ to <c>{pref_public_key_algs, ['ssh-dss','ssh-rsa']}</c>.
+ </p>
</item>
<tag><c><![CDATA[{pref_public_key_algs, list()}]]></c></tag>
<item>
- <note>
- <p>This option is kept for compatibility. It is ignored if the <c>preferred_algorithms</c>
- option is used. The equivalence of <c>{pref_public_key_algs,['ssh-dss']}</c> is
- <c>{preferred_algorithms, [{public_key,['ssh-dss']}]}</c>.</p>
- </note>
- <p>List of public key algorithms to try to use.
- <c>'ssh-rsa'</c> and <c>'ssh-dss'</c> are available.
- Overrides <c><![CDATA[{public_key_alg, 'ssh-rsa' | 'ssh-dss'}]]></c></p>
+ <p>List of user (client) public key algorithms to try to use.</p>
+ <p>The default value is
+ <c><![CDATA[['ssh-rsa','ssh-dss','ecdsa-sha2-nistp256','ecdsa-sha2-nistp384','ecdsa-sha2-nistp521'] ]]></c>
+ </p>
+ <p>If there is no public key of a specified type available, the corresponding entry is ignored.</p>
</item>
<tag><c><![CDATA[{preferred_algorithms, algs_list()}]]></c></tag>
@@ -248,6 +232,7 @@
<p>List of algorithms to use in the algorithm negotiation. The default <c>algs_list()</c> can
be obtained from <seealso marker="#default_algorithms/0">default_algorithms/0</seealso>.
</p>
+ <p>If an alg_entry() is missing in the algs_list(), the default value is used for that entry.</p>
<p>Here is an example of this option:</p>
<code>
{preferred_algorithms,
@@ -258,9 +243,9 @@
{compression,[none,zlib]}
}
</code>
- <p>The example specifies different algorithms in the two directions (client2server and server2client), for cipher but specifies the same
-algorithms for mac and compression in both directions. The kex (key exchange) and public key algorithms are set to their default values,
-kex is implicit but public_key is set explicitly.</p>
+ <p>The example specifies different algorithms in the two directions (client2server and server2client),
+ for cipher but specifies the same algorithms for mac and compression in both directions.
+ The kex (key exchange) is implicit but public_key is set explicitly.</p>
<warning>
<p>Changing the values can make a connection less secure. Do not change unless you
@@ -296,11 +281,13 @@ kex is implicit but public_key is set explicitly.</p>
password, if the password authentication method is
attempted.</p>
</item>
- <tag><c><![CDATA[{key_cb, atom()}]]></c></tag>
+ <tag><c><![CDATA[{key_cb, key_cb()}]]></c></tag>
<item>
- <p>Module implementing the behaviour
- <seealso marker="ssh_client_key_api">ssh_client_key_api</seealso>.
- Can be used to customize the handling of public keys.
+ <p>Module implementing the behaviour <seealso
+ marker="ssh_client_key_api">ssh_client_key_api</seealso>. Can be used to
+ customize the handling of public keys. If callback options are provided
+ along with the module name, they are made available to the callback
+ module via the options passed to it under the key 'key_cb_private'.
</p>
</item>
<tag><c><![CDATA[{quiet_mode, atom() = boolean()}]]></c></tag>
@@ -431,10 +418,10 @@ kex is implicit but public_key is set explicitly.</p>
<c><![CDATA["publickey,keyboard-interactive,password"]]></c></p>
</item>
- <tag><c><![CDATA[{auth_method_kb_interactive_data, PromptTexts}]]>
- <br/>where:
- <br/>PromptTexts = kb_int_tuple() | fun(Peer::{IP::tuple(),Port::integer()}, User::string(), Service::string()) -> kb_int_tuple()
- <br/>kb_int_tuple() = {Name::string(), Instruction::string(), Prompt::string(), Echo::boolean()}</c>
+ <tag><c><![CDATA[{auth_method_kb_interactive_data, PromptTexts}]]></c>
+ <br/><c>where:</c>
+ <br/><c>PromptTexts = kb_int_tuple() | fun(Peer::{IP::tuple(),Port::integer()}, User::string(), Service::string()) -> kb_int_tuple()</c>
+ <br/><c>kb_int_tuple() = {Name::string(), Instruction::string(), Prompt::string(), Echo::boolean()}</c>
</tag>
<item>
<p>Sets the text strings that the daemon sends to the client for presentation to the user when using <c>keyboar-interactive</c> authentication. If the fun/3 is used, it is called when the actual authentication occurs and may therefore return dynamic data like time, remote ip etc.</p>
@@ -464,6 +451,7 @@ kex is implicit but public_key is set explicitly.</p>
<p>List of algorithms to use in the algorithm negotiation. The default <c>algs_list()</c> can
be obtained from <seealso marker="#default_algorithms/0">default_algorithms/0</seealso>.
</p>
+ <p>If an alg_entry() is missing in the algs_list(), the default value is used for that entry.</p>
<p>Here is an example of this option:</p>
<code>
{preferred_algorithms,
@@ -474,9 +462,9 @@ kex is implicit but public_key is set explicitly.</p>
{compression,[none,zlib]}
}
</code>
- <p>The example specifies different algorithms in the two directions (client2server and server2client), for cipher but specifies the same
-algorithms for mac and compression in both directions. The kex (key exchange) and public key algorithms are set to their default values,
-kex is implicit but public_key is set explicitly.</p>
+ <p>The example specifies different algorithms in the two directions (client2server and server2client),
+ for cipher but specifies the same algorithms for mac and compression in both directions.
+ The kex (key exchange) is implicit but public_key is set explicitly.</p>
<warning>
<p>Changing the values can make a connection less secure. Do not change unless you
@@ -528,29 +516,29 @@ kex is implicit but public_key is set explicitly.</p>
<item>
<p>Provides a function for password validation. This could used for calling an external system or if
passwords should be stored as a hash. The fun returns:
- <list type="bulleted">
- <item><c>true</c> if the user and password is valid and</item>
- <item><c>false</c> otherwise.</item>
- </list>
</p>
+ <list type="bulleted">
+ <item><c>true</c> if the user and password is valid and</item>
+ <item><c>false</c> otherwise.</item>
+ </list>
<p>This fun can also be used to make delays in authentication tries for example by calling
<seealso marker="stdlib:timer#sleep/1">timer:sleep/1</seealso>. To facilitate counting of failed tries
the <c>State</c> variable could be used. This state is per connection only. The first time the pwdfun
is called for a connection, the <c>State</c> variable has the value <c>undefined</c>.
The pwdfun can return - in addition to the values above - a new state
as:
- <list type="bulleted">
- <item><c>{true, NewState:any()}</c> if the user and password is valid or</item>
- <item><c>{false, NewState:any()}</c> if the user or password is invalid</item>
- </list>
</p>
+ <list type="bulleted">
+ <item><c>{true, NewState:any()}</c> if the user and password is valid or</item>
+ <item><c>{false, NewState:any()}</c> if the user or password is invalid</item>
+ </list>
<p>A third usage is to block login attempts from a missbehaving peer. The <c>State</c> described above
can be used for this. In addition to the responses above, the following return value is introduced:
+ </p>
<list type="bulleted">
<item><c>disconnect</c> if the connection should be closed immediately after sending a SSH_MSG_DISCONNECT
message.</item>
</list>
- </p>
</item>
<tag><c><![CDATA[{pwdfun, fun(User::string(), Password::string()) -> boolean()}]]></c></tag>
@@ -631,11 +619,13 @@ kex is implicit but public_key is set explicitly.</p>
</p>
</item>
- <tag><c><![CDATA[{key_cb, atom()}]]></c></tag>
+ <tag><c><![CDATA[{key_cb, key_cb()}]]></c></tag>
<item>
- <p>Module implementing the behaviour
- <seealso marker="ssh_server_key_api">ssh_server_key_api</seealso>.
- Can be used to customize the handling of public keys.
+ <p>Module implementing the behaviour <seealso
+ marker="ssh_server_key_api">ssh_server_key_api</seealso>. Can be used to
+ customize the handling of public keys. If callback options are provided
+ along with the module name, they are made available to the callback
+ module via the options passed to it under the key 'key_cb_private'.
</p>
</item>
diff --git a/lib/ssh/doc/src/ssh_app.xml b/lib/ssh/doc/src/ssh_app.xml
index 4c85585820..f6ce44c015 100644
--- a/lib/ssh/doc/src/ssh_app.xml
+++ b/lib/ssh/doc/src/ssh_app.xml
@@ -4,7 +4,7 @@
<appref>
<header>
<copyright>
- <year>2012</year><year>2013</year>
+ <year>2012</year><year>2015</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -41,15 +41,18 @@
<section>
<title>DEPENDENCIES</title>
- <p>The <c>ssh</c> application uses the applications <c>public_key</c> and
- <c>crypto</c> to handle public keys and encryption. Hence, these
+ <p>The <c>ssh</c> application uses the applications
+ <seealso marker="public_key:public_key">public_key</seealso> and
+ <seealso marker="crypto:crypto">crypto</seealso>
+ to handle public keys and encryption. Hence, these
applications must be loaded for the <c>ssh</c> application to work. In
an embedded environment this means that they must be started with
- <c>application:start/[1,2]</c> before the <c>ssh</c> application is started.
+ <seealso marker="kernel:application#start/1">application:start/1,2</seealso> before the
+ <c>ssh</c> application is started.
</p>
</section>
- <section>
+ <section>
<title>CONFIGURATION</title>
<p>The <c>ssh</c> application does not have an application-
@@ -62,10 +65,13 @@
<item><c>authorized_keys2</c></item>
<item><c>id_dsa</c></item>
<item><c>id_rsa</c></item>
+ <item><c>id_ecdsa</c></item>
<item><c>ssh_host_dsa_key</c></item>
<item><c>ssh_host_rsa_key</c></item>
+ <item><c>ssh_host_ecdsa_key</c></item>
</list>
<p>By default, <c>ssh</c> looks for <c>id_dsa</c>, <c>id_rsa</c>,
+ <c>id_ecdsa_key</c>,
<c>known_hosts</c>, and <c>authorized_keys</c> in ~/.ssh,
and for the host key files in <c>/etc/ssh</c>. These locations can be changed
by the options <c>user_dir</c> and <c>system_dir</c>.
@@ -79,7 +85,7 @@
</section>
<section>
<title>Public Keys</title>
- <p><c>id_dsa</c> and <c>id_rsa</c> are the users private key files.
+ <p><c>id_dsa</c>, <c>id_rsa</c> and <c>id_ecdsa</c> are the users private key files.
Notice that the public key is part of the private key so the <c>ssh</c>
application does not use the <c>id_&lt;*>.pub</c> files. These are
for the user's convenience when it is needed to convey the user's
@@ -104,8 +110,8 @@
<section>
<title>Host Keys</title>
<p>RSA and DSA host keys are supported and are
- expected to be found in files named <c>ssh_host_rsa_key</c> and
- <c>ssh_host_dsa_key</c>.
+ expected to be found in files named <c>ssh_host_rsa_key</c>,
+ <c>ssh_host_dsa_key</c> and <c>ssh_host_ecdsa_key</c>.
</p>
</section>
<section>
@@ -114,6 +120,198 @@
</section>
<section>
+ <marker id="supported"/>
+ <title>SUPPORTED SPECIFICATIONS AND STANDARDS</title>
+ <p>The supported SSH version is 2.0.</p>
+ </section>
+ <section>
+ <title>Algorithms</title>
+ <p>The actual set of algorithms may vary depending on which OpenSSL crypto library that is installed on the machine.
+ For the list on a particular installation, use the command
+ <seealso marker="ssh:ssh#default_algorithms/0">ssh:default_algorithms/0</seealso>.
+ The user may override the default algorithm configuration both on the server side and the client side.
+ See the option <c>preferred_algorithms</c> in the <seealso marker="ssh:ssh#daemon/1">ssh:daemon/1,2,3</seealso> and
+ <seealso marker="ssh:ssh#connect/3">ssh:connect/3,4</seealso> functions.
+ </p>
+
+ <p>Supported algorithms are:</p>
+
+ <taglist>
+ <tag>Key exchange algorithms</tag>
+ <item>
+ <list type="bulleted">
+ <item>ecdh-sha2-nistp256</item>
+ <item>ecdh-sha2-nistp384</item>
+ <item>ecdh-sha2-nistp521</item>
+ <item>diffie-hellman-group-exchange-sha1</item>
+ <item>diffie-hellman-group-exchange-sha256</item>
+ <item>diffie-hellman-group14-sha1</item>
+ <item>diffie-hellman-group1-sha1</item>
+ </list>
+ </item>
+
+ <tag>Public key algorithms</tag>
+ <item>
+ <list type="bulleted">
+ <item>ecdsa-sha2-nistp256</item>
+ <item>ecdsa-sha2-nistp384</item>
+ <item>ecdsa-sha2-nistp521</item>
+ <item>ssh-rsa</item>
+ <item>ssh-dss</item>
+ </list>
+ </item>
+
+ <tag>MAC algorithms</tag>
+ <item>
+ <list type="bulleted">
+ <item>hmac-sha2-256</item>
+ <item>hmac-sha2-512</item>
+ <item>hmac-sha1</item>
+ </list>
+ </item>
+
+ <tag>Encryption algorithms (ciphers)</tag>
+ <item>
+ <list type="bulleted">
+ <item>[email protected] (AEAD_AES_128_GCM)</item>
+ <item>[email protected] (AEAD_AES_256_GCM)</item>
+ <item>aes128-ctr</item>
+ <item>aes192-ctr</item>
+ <item>aes256-ctr</item>
+ <item>aes128-cbc</item>
+ <item>3des-cbc</item>
+ </list>
+ <p>Following the internet de-facto standard, the cipher and mac algorithm AEAD_AES_128_GCM is selected when the
+ cipher [email protected] is negotiated. The cipher and mac algorithm AEAD_AES_256_GCM is selected when the
+ cipher [email protected] is negotiated.
+ </p>
+ <p>See the text at the description of <seealso marker="#rfc5647_note">the rfc 5647 further down</seealso>
+ for more information.
+ </p>
+ </item>
+
+ <tag>Compression algorithms</tag>
+ <item>
+ <list type="bulleted">
+ <item>none</item>
+ <item>[email protected]</item>
+ <item>zlib</item>
+ </list>
+ </item>
+ </taglist>
+ </section>
+ <section>
+ <title>Unicode support</title>
+ <p>Unicode filenames are supported if the emulator and the underlaying OS support it. See section DESCRIPTION in the
+ <seealso marker="kernel:file">file</seealso> manual page in <c>kernel</c> for information about this subject.
+ </p>
+ <p>The shell and the cli both support unicode.
+ </p>
+ </section>
+
+ <section>
+ <title>Rfcs</title>
+ <p>The following rfc:s are supported:</p>
+ <list type="bulleted">
+ <item><url href="https://tools.ietf.org/html/rfc4251">RFC 4251</url>, The Secure Shell (SSH) Protocol Architecture.
+ <p>Except</p>
+ <list type="bulleted">
+ <item>9.4.6 Host-Based Authentication</item>
+ <item>9.5.2 Proxy Forwarding</item>
+ <item>9.5.3 X11 Forwarding</item>
+ </list>
+ <p/>
+ </item>
+
+ <item><url href="https://tools.ietf.org/html/rfc4252">RFC 4252</url>, The Secure Shell (SSH) Authentication Protocol.
+ <p>Except</p>
+ <list type="bulleted">
+ <item>9. Host-Based Authentication: "hostbased"</item>
+ </list>
+ <p/>
+ </item>
+
+ <item><url href="https://tools.ietf.org/html/rfc4253">RFC 4253</url>, The Secure Shell (SSH) Transport Layer Protocol.
+ <p></p>
+ </item>
+
+ <item><url href="https://tools.ietf.org/html/rfc4254">RFC 4254</url>, The Secure Shell (SSH) Connection Protocol.
+ <p>Except</p>
+ <list type="bulleted">
+ <item>6.3. X11 Forwarding</item>
+ <item>7. TCP/IP Port Forwarding</item>
+ </list>
+ <p/>
+ </item>
+
+ <item><url href="https://tools.ietf.org/html/rfc4256">RFC 4256</url>, Generic Message Exchange Authentication for
+ the Secure Shell Protocol (SSH).
+ <p>Except</p>
+ <list type="bulleted">
+ <item><c>num-prompts > 1</c></item>
+ <item>password changing</item>
+ <item>other identification methods than userid-password</item>
+ </list>
+ <p/>
+ </item>
+
+ <item><url href="https://tools.ietf.org/html/rfc4419">RFC 4419</url>, Diffie-Hellman Group Exchange for
+ the Secure Shell (SSH) Transport Layer Protocol.
+ <p/>
+ </item>
+
+ <item><url href="https://tools.ietf.org/html/rfc4716">RFC 4716</url>, The Secure Shell (SSH) Public Key File Format.
+ <p/>
+ </item>
+
+ <item><url href="https://tools.ietf.org/html/rfc5647">RFC 5647</url>, AES Galois Counter Mode for
+ the Secure Shell Transport Layer Protocol.
+ <p><marker id="rfc5647_note"/>There is an ambiguity in the synchronized selection of cipher and mac algorithm.
+ This is resolved by OpenSSH in the ciphers [email protected] and [email protected] which are implemented.
+ If the explicit ciphers and macs AEAD_AES_128_GCM or AEAD_AES_256_GCM are needed,
+ they could be enabled with the option preferred_algorithms.
+ </p>
+ <warning>
+ <p>
+ If the client or the server is not Erlang/OTP, it is the users responsibility to check that
+ other implementation has the same interpretation of AEAD_AES_*_GCM as the Erlang/OTP SSH before
+ enabling them. The aes*[email protected] variants are always safe to use since they lack the
+ ambiguity.
+ </p>
+ </warning>
+ <p>The second paragraph in section 5.1 is resolved as:</p>
+ <list type="ordered">
+ <item>If the negotiated cipher is AEAD_AES_128_GCM, the mac algorithm is set to AEAD_AES_128_GCM.</item>
+ <item>If the negotiated cipher is AEAD_AES_256_GCM, the mac algorithm is set to AEAD_AES_256_GCM.</item>
+ <item>If the mac algorithm is AEAD_AES_128_GCM, the cipher is set to AEAD_AES_128_GCM.</item>
+ <item>If the mac algorithm is AEAD_AES_256_GCM, the cipher is set to AEAD_AES_256_GCM.</item>
+ </list>
+ <p>The first rule that matches when read in order from the top is applied</p>
+ </item>
+
+ <item><url href="https://tools.ietf.org/html/rfc5656">RFC 5656</url>, Elliptic Curve Algorithm Integration in
+ the Secure Shell Transport Layer.
+ <p>Except</p>
+ <list type="bulleted">
+ <item>5. ECMQV Key Exchange</item>
+ <item>6.4. ECMQV Key Exchange and Verification Method Name</item>
+ <item>7.2. ECMQV Message Numbers</item>
+ <item>10.2. Recommended Curves</item>
+ </list>
+ <p/>
+ </item>
+
+ <item><url href="https://tools.ietf.org/html/rfc6668">RFC 6668</url>, SHA-2 Data Integrity Verification for
+ the Secure Shell (SSH) Transport Layer Protocol
+ <p>Comment: Defines hmac-sha2-256 and hmac-sha2-512
+ </p>
+ </item>
+
+ </list>
+
+ </section>
+
+ <section>
<title>SEE ALSO</title>
<p><seealso marker="kernel:application">application(3)</seealso></p>
</section>
diff --git a/lib/ssh/doc/src/ssh_connection.xml b/lib/ssh/doc/src/ssh_connection.xml
index 9a7bb09b12..150d46a9a2 100644
--- a/lib/ssh/doc/src/ssh_connection.xml
+++ b/lib/ssh/doc/src/ssh_connection.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>2008</year>
- <year>2014</year>
+ <year>2015</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -31,15 +31,15 @@
<rev></rev>
</header>
<module>ssh_connection</module>
- <modulesummary>This module provides API functions to send
- <url href="http://www.ietf.org/rfc/rfc4254.txt"> SSH Connection Protocol </url>
- events to the other side of an SSH channel.
+ <modulesummary>
+ This module provides API functions to send SSH Connection Protocol
+ events to the other side of an SSH channel.
</modulesummary>
<description>
- <p>The SSH Connection Protocol is used by clients and servers,
- that is, SSH channels, to communicate over the SSH connection. The
- API functions in this module send SSH Connection Protocol events,
+ <p>The <url href="http://www.ietf.org/rfc/rfc4254.txt">SSH Connection Protocol</url>
+ is used by clients and servers, that is, SSH channels, to communicate over the
+ SSH connection. The API functions in this module send SSH Connection Protocol events,
which are received as messages by the remote channel.
If the receiving channel is an Erlang process, the
messages have the format
@@ -373,6 +373,9 @@
<desc>
<p>Is to be called by client- and server-channel processes to send data to each other.
</p>
+ <p>The function <seealso marker="ssh:ssh_connection#subsystem/4">subsystem/4</seealso> and subsequent
+ calls of <c>send/3,4,5</c> must be executed in the same process.
+ </p>
</desc>
</func>
@@ -454,6 +457,9 @@
<p>Is to be called by a client-channel process for requesting to execute a predefined
subsystem on the server.
</p>
+ <p>The function <c>subsystem/4</c> and subsequent calls of
+ <seealso marker="ssh:ssh_connection#send/3">send/3,4,5</seealso> must be executed in the same process.
+ </p>
</desc>
</func>
diff --git a/lib/ssh/doc/src/ssh_server_key_api.xml b/lib/ssh/doc/src/ssh_server_key_api.xml
index efb2c436e8..a0694ca8d9 100644
--- a/lib/ssh/doc/src/ssh_server_key_api.xml
+++ b/lib/ssh/doc/src/ssh_server_key_api.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>2012</year>
- <year>2013</year>
+ <year>2015</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -75,7 +75,7 @@
<d>Host key algorithm. Is to support <c>'ssh-rsa' | 'ssh-dss'</c>, but more algorithms
can be handled.</d>
<v>DaemonOptions = proplists:proplist()</v>
- <d>Options provided to <seealso marker="ssh#daemon-2">ssh:daemon/[2,3]</seealso>.</d>
+ <d>Options provided to <seealso marker="ssh#daemon-2">ssh:daemon/[2,3]</seealso>.</d>
<v>Key = private_key()</v>
<d>Private key of the host matching the <c>Algorithm</c>.</d>
<v>Reason = term()</v>
diff --git a/lib/ssh/doc/src/ssh_sftp.xml b/lib/ssh/doc/src/ssh_sftp.xml
index 17800fac5d..c6ca0f161a 100644
--- a/lib/ssh/doc/src/ssh_sftp.xml
+++ b/lib/ssh/doc/src/ssh_sftp.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2005</year><year>2014</year>
+ <year>2005</year><year>2015</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -61,20 +61,23 @@
<funcs>
<func>
- <name>apread(ChannelPid, Handle, Position, Len) -> {async, N} | {error, Error}</name>
- <v>ChannelPid = pid()</v>
- <v>Handle = term()</v>
- <v>Position = integer()</v>
- <v>Len = integer()</v>
- <v>N = term()</v>
- <v>Reason = term()</v>
-
- <desc><p>The <c><![CDATA[apread]]></c> function reads from a specified position,
- combining the <c><![CDATA[position]]></c> and <c><![CDATA[aread]]></c> functions.</p>
+ <name>apread(ChannelPid, Handle, Position, Len) -> {async, N} | {error, Reason}</name>
+ <fsummary>Reads asynchronously from an open file.</fsummary>
+ <type>
+ <v>ChannelPid = pid()</v>
+ <v>Handle = term()</v>
+ <v>Position = integer()</v>
+ <v>Len = integer()</v>
+ <v>N = term()</v>
+ <v>Reason = term()</v>
+ </type>
+
+ <desc><p>The <c><![CDATA[apread]]></c> function reads from a specified position,
+ combining the <c><![CDATA[position]]></c> and <c><![CDATA[aread]]></c> functions.</p>
<p><seealso marker="#apread-4">ssh_sftp:apread/4</seealso></p> </desc>
- </func>
-
- <func>
+ </func>
+
+ <func>
<name>apwrite(ChannelPid, Handle, Position, Data) -> ok | {error, Reason}</name>
<fsummary>Writes asynchronously to an open file.</fsummary>
<type>
diff --git a/lib/ssh/doc/src/using_ssh.xml b/lib/ssh/doc/src/using_ssh.xml
index 91185a0f6e..6826f20fb3 100644
--- a/lib/ssh/doc/src/using_ssh.xml
+++ b/lib/ssh/doc/src/using_ssh.xml
@@ -234,7 +234,7 @@
<title>SFTP Client with TAR Compression and Encryption</title>
<p>Example of writing and then reading a tar file follows:</p>
- <code type="erlang">
+ <code type="erl">
{ok,HandleWrite} = ssh_sftp:open_tar(ChannelPid, ?tar_file_name, [write]),
ok = erl_tar:add(HandleWrite, .... ),
ok = erl_tar:add(HandleWrite, .... ),
@@ -249,10 +249,10 @@
</code>
<p>The previous write and read example can be extended with encryption and decryption as follows:</p>
- <code type="erlang">
+ <code type="erl">
%% First three parameters depending on which crypto type we select:
Key = &lt;&lt;"This is a 256 bit key. abcdefghi">>,
-Ivec0 = crypto:rand_bytes(16),
+Ivec0 = crypto:strong_rand_bytes(16),
DataSize = 1024, % DataSize rem 16 = 0 for aes_cbc
%% Initialization of the CryptoState, in this case it is the Ivector.
diff --git a/lib/ssh/doc/standard/draft-ietf-secsh-architecture-15.2.ps b/lib/ssh/doc/standard/draft-ietf-secsh-architecture-15.2.ps
deleted file mode 100644
index d766a933b4..0000000000
--- a/lib/ssh/doc/standard/draft-ietf-secsh-architecture-15.2.ps
+++ /dev/null
@@ -1,3315 +0,0 @@
-%!PS-Adobe-3.0
-%%BoundingBox: 75 0 595 747
-%%Title: Enscript Output
-%%For: Magnus Thoang
-%%Creator: GNU enscript 1.6.1
-%%CreationDate: Fri Oct 31 13:31:26 2003
-%%Orientation: Portrait
-%%Pages: 15 0
-%%DocumentMedia: A4 595 842 0 () ()
-%%DocumentNeededResources: (atend)
-%%EndComments
-%%BeginProlog
-%%BeginProcSet: PStoPS 1 15
-userdict begin
-[/showpage/erasepage/copypage]{dup where{pop dup load
- type/operatortype eq{1 array cvx dup 0 3 index cvx put
- bind def}{pop}ifelse}{pop}ifelse}forall
-[/letter/legal/executivepage/a4/a4small/b5/com10envelope
- /monarchenvelope/c5envelope/dlenvelope/lettersmall/note
- /folio/quarto/a5]{dup where{dup wcheck{exch{}put}
- {pop{}def}ifelse}{pop}ifelse}forall
-/setpagedevice {pop}bind 1 index where{dup wcheck{3 1 roll put}
- {pop def}ifelse}{def}ifelse
-/PStoPSmatrix matrix currentmatrix def
-/PStoPSxform matrix def/PStoPSclip{clippath}def
-/defaultmatrix{PStoPSmatrix exch PStoPSxform exch concatmatrix}bind def
-/initmatrix{matrix defaultmatrix setmatrix}bind def
-/initclip[{matrix currentmatrix PStoPSmatrix setmatrix
- [{currentpoint}stopped{$error/newerror false put{newpath}}
- {/newpath cvx 3 1 roll/moveto cvx 4 array astore cvx}ifelse]
- {[/newpath cvx{/moveto cvx}{/lineto cvx}
- {/curveto cvx}{/closepath cvx}pathforall]cvx exch pop}
- stopped{$error/errorname get/invalidaccess eq{cleartomark
- $error/newerror false put cvx exec}{stop}ifelse}if}bind aload pop
- /initclip dup load dup type dup/operatortype eq{pop exch pop}
- {dup/arraytype eq exch/packedarraytype eq or
- {dup xcheck{exch pop aload pop}{pop cvx}ifelse}
- {pop cvx}ifelse}ifelse
- {newpath PStoPSclip clip newpath exec setmatrix} bind aload pop]cvx def
-/initgraphics{initmatrix newpath initclip 1 setlinewidth
- 0 setlinecap 0 setlinejoin []0 setdash 0 setgray
- 10 setmiterlimit}bind def
-end
-%%EndProcSet
-%%BeginResource: procset Enscript-Prolog 1.6 1
-%
-% Procedures.
-%
-
-/_S { % save current state
- /_s save def
-} def
-/_R { % restore from saved state
- _s restore
-} def
-
-/S { % showpage protecting gstate
- gsave
- showpage
- grestore
-} bind def
-
-/MF { % fontname newfontname -> - make a new encoded font
- /newfontname exch def
- /fontname exch def
-
- /fontdict fontname findfont def
- /newfont fontdict maxlength dict def
-
- fontdict {
- exch
- dup /FID eq {
- % skip FID pair
- pop pop
- } {
- % copy to the new font dictionary
- exch newfont 3 1 roll put
- } ifelse
- } forall
-
- newfont /FontName newfontname put
-
- % insert only valid encoding vectors
- encoding_vector length 256 eq {
- newfont /Encoding encoding_vector put
- } if
-
- newfontname newfont definefont pop
-} def
-
-/SF { % fontname width height -> - set a new font
- /height exch def
- /width exch def
-
- findfont
- [width 0 0 height 0 0] makefont setfont
-} def
-
-/SUF { % fontname width height -> - set a new user font
- /height exch def
- /width exch def
-
- /F-gs-user-font MF
- /F-gs-user-font width height SF
-} def
-
-/M {moveto} bind def
-/s {show} bind def
-
-/Box { % x y w h -> - define box path
- /d_h exch def /d_w exch def /d_y exch def /d_x exch def
- d_x d_y moveto
- d_w 0 rlineto
- 0 d_h rlineto
- d_w neg 0 rlineto
- closepath
-} def
-
-/bgs { % x y height blskip gray str -> - show string with bg color
- /str exch def
- /gray exch def
- /blskip exch def
- /height exch def
- /y exch def
- /x exch def
-
- gsave
- x y blskip sub str stringwidth pop height Box
- gray setgray
- fill
- grestore
- x y M str s
-} def
-
-% Highlight bars.
-/highlight_bars { % nlines lineheight output_y_margin gray -> -
- gsave
- setgray
- /ymarg exch def
- /lineheight exch def
- /nlines exch def
-
- % This 2 is just a magic number to sync highlight lines to text.
- 0 d_header_y ymarg sub 2 sub translate
-
- /cw d_output_w cols div def
- /nrows d_output_h ymarg 2 mul sub lineheight div cvi def
-
- % for each column
- 0 1 cols 1 sub {
- cw mul /xp exch def
-
- % for each rows
- 0 1 nrows 1 sub {
- /rn exch def
- rn lineheight mul neg /yp exch def
- rn nlines idiv 2 mod 0 eq {
- % Draw highlight bar. 4 is just a magic indentation.
- xp 4 add yp cw 8 sub lineheight neg Box fill
- } if
- } for
- } for
-
- grestore
-} def
-
-% Line highlight bar.
-/line_highlight { % x y width height gray -> -
- gsave
- /gray exch def
- Box gray setgray fill
- grestore
-} def
-
-% Column separator lines.
-/column_lines {
- gsave
- .1 setlinewidth
- 0 d_footer_h translate
- /cw d_output_w cols div def
- 1 1 cols 1 sub {
- cw mul 0 moveto
- 0 d_output_h rlineto stroke
- } for
- grestore
-} def
-
-% Column borders.
-/column_borders {
- gsave
- .1 setlinewidth
- 0 d_footer_h moveto
- 0 d_output_h rlineto
- d_output_w 0 rlineto
- 0 d_output_h neg rlineto
- closepath stroke
- grestore
-} def
-
-% Do the actual underlay drawing
-/draw_underlay {
- ul_style 0 eq {
- ul_str true charpath stroke
- } {
- ul_str show
- } ifelse
-} def
-
-% Underlay
-/underlay { % - -> -
- gsave
- 0 d_page_h translate
- d_page_h neg d_page_w atan rotate
-
- ul_gray setgray
- ul_font setfont
- /dw d_page_h dup mul d_page_w dup mul add sqrt def
- ul_str stringwidth pop dw exch sub 2 div ul_h_ptsize -2 div moveto
- draw_underlay
- grestore
-} def
-
-/user_underlay { % - -> -
- gsave
- ul_x ul_y translate
- ul_angle rotate
- ul_gray setgray
- ul_font setfont
- 0 0 ul_h_ptsize 2 div sub moveto
- draw_underlay
- grestore
-} def
-
-% Page prefeed
-/page_prefeed { % bool -> -
- statusdict /prefeed known {
- statusdict exch /prefeed exch put
- } {
- pop
- } ifelse
-} def
-
-% Wrapped line markers
-/wrapped_line_mark { % x y charwith charheight type -> -
- /type exch def
- /h exch def
- /w exch def
- /y exch def
- /x exch def
-
- type 2 eq {
- % Black boxes (like TeX does)
- gsave
- 0 setlinewidth
- x w 4 div add y M
- 0 h rlineto w 2 div 0 rlineto 0 h neg rlineto
- closepath fill
- grestore
- } {
- type 3 eq {
- % Small arrows
- gsave
- .2 setlinewidth
- x w 2 div add y h 2 div add M
- w 4 div 0 rlineto
- x w 4 div add y lineto stroke
-
- x w 4 div add w 8 div add y h 4 div add M
- x w 4 div add y lineto
- w 4 div h 8 div rlineto stroke
- grestore
- } {
- % do nothing
- } ifelse
- } ifelse
-} def
-
-% EPSF import.
-
-/BeginEPSF {
- /b4_Inc_state save def % Save state for cleanup
- /dict_count countdictstack def % Count objects on dict stack
- /op_count count 1 sub def % Count objects on operand stack
- userdict begin
- /showpage { } def
- 0 setgray 0 setlinecap
- 1 setlinewidth 0 setlinejoin
- 10 setmiterlimit [ ] 0 setdash newpath
- /languagelevel where {
- pop languagelevel
- 1 ne {
- false setstrokeadjust false setoverprint
- } if
- } if
-} bind def
-
-/EndEPSF {
- count op_count sub { pos } repeat % Clean up stacks
- countdictstack dict_count sub { end } repeat
- b4_Inc_state restore
-} bind def
-
-% Check PostScript language level.
-/languagelevel where {
- pop /gs_languagelevel languagelevel def
-} {
- /gs_languagelevel 1 def
-} ifelse
-%%EndResource
-%%BeginResource: procset Enscript-Encoding-88591 1.6 1
-/encoding_vector [
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/space /exclam /quotedbl /numbersign
-/dollar /percent /ampersand /quoteright
-/parenleft /parenright /asterisk /plus
-/comma /hyphen /period /slash
-/zero /one /two /three
-/four /five /six /seven
-/eight /nine /colon /semicolon
-/less /equal /greater /question
-/at /A /B /C
-/D /E /F /G
-/H /I /J /K
-/L /M /N /O
-/P /Q /R /S
-/T /U /V /W
-/X /Y /Z /bracketleft
-/backslash /bracketright /asciicircum /underscore
-/quoteleft /a /b /c
-/d /e /f /g
-/h /i /j /k
-/l /m /n /o
-/p /q /r /s
-/t /u /v /w
-/x /y /z /braceleft
-/bar /braceright /tilde /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/space /exclamdown /cent /sterling
-/currency /yen /brokenbar /section
-/dieresis /copyright /ordfeminine /guillemotleft
-/logicalnot /hyphen /registered /macron
-/degree /plusminus /twosuperior /threesuperior
-/acute /mu /paragraph /bullet
-/cedilla /onesuperior /ordmasculine /guillemotright
-/onequarter /onehalf /threequarters /questiondown
-/Agrave /Aacute /Acircumflex /Atilde
-/Adieresis /Aring /AE /Ccedilla
-/Egrave /Eacute /Ecircumflex /Edieresis
-/Igrave /Iacute /Icircumflex /Idieresis
-/Eth /Ntilde /Ograve /Oacute
-/Ocircumflex /Otilde /Odieresis /multiply
-/Oslash /Ugrave /Uacute /Ucircumflex
-/Udieresis /Yacute /Thorn /germandbls
-/agrave /aacute /acircumflex /atilde
-/adieresis /aring /ae /ccedilla
-/egrave /eacute /ecircumflex /edieresis
-/igrave /iacute /icircumflex /idieresis
-/eth /ntilde /ograve /oacute
-/ocircumflex /otilde /odieresis /divide
-/oslash /ugrave /uacute /ucircumflex
-/udieresis /yacute /thorn /ydieresis
-] def
-%%EndResource
-%%EndProlog
-%%BeginSetup
-%%IncludeResource: font Courier-Bold
-%%IncludeResource: font Courier
-/HFpt_w 10 def
-/HFpt_h 10 def
-/Courier-Bold /HF-gs-font MF
-/HF /HF-gs-font findfont [HFpt_w 0 0 HFpt_h 0 0] makefont def
-/Courier /F-gs-font MF
-/F-gs-font 10 10 SF
-/#copies 1 def
-/d_page_w 520 def
-/d_page_h 747 def
-/d_header_x 0 def
-/d_header_y 747 def
-/d_header_w 520 def
-/d_header_h 0 def
-/d_footer_x 0 def
-/d_footer_y 0 def
-/d_footer_w 520 def
-/d_footer_h 0 def
-/d_output_w 520 def
-/d_output_h 747 def
-/cols 1 def
-userdict/PStoPSxform PStoPSmatrix matrix currentmatrix
- matrix invertmatrix matrix concatmatrix
- matrix invertmatrix put
-%%EndSetup
-%%Page: (0,1) 1
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 1 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 701 M
-(Network Working Group T. Ylonen) s
-5 690 M
-(Internet-Draft SSH Communications Security Corp) s
-5 679 M
-(Expires: March 31, 2004 D. Moffat, Ed.) s
-5 668 M
-( Sun Microsystems, Inc) s
-5 657 M
-( Oct 2003) s
-5 624 M
-( SSH Protocol Architecture) s
-5 613 M
-( draft-ietf-secsh-architecture-15.txt) s
-5 591 M
-(Status of this Memo) s
-5 569 M
-( This document is an Internet-Draft and is in full conformance with) s
-5 558 M
-( all provisions of Section 10 of RFC2026.) s
-5 536 M
-( Internet-Drafts are working documents of the Internet Engineering) s
-5 525 M
-( Task Force \(IETF\), its areas, and its working groups. Note that other) s
-5 514 M
-( groups may also distribute working documents as Internet-Drafts.) s
-5 492 M
-( Internet-Drafts are draft documents valid for a maximum of six months) s
-5 481 M
-( and may be updated, replaced, or obsoleted by other documents at any) s
-5 470 M
-( time. It is inappropriate to use Internet-Drafts as reference) s
-5 459 M
-( material or to cite them other than as "work in progress.") s
-5 437 M
-( The list of current Internet-Drafts can be accessed at http://) s
-5 426 M
-( www.ietf.org/ietf/1id-abstracts.txt.) s
-5 404 M
-( The list of Internet-Draft Shadow Directories can be accessed at) s
-5 393 M
-( http://www.ietf.org/shadow.html.) s
-5 371 M
-( This Internet-Draft will expire on March 31, 2004.) s
-5 349 M
-(Copyright Notice) s
-5 327 M
-( Copyright \(C\) The Internet Society \(2003\). All Rights Reserved.) s
-5 305 M
-(Abstract) s
-5 283 M
-( SSH is a protocol for secure remote login and other secure network) s
-5 272 M
-( services over an insecure network. This document describes the) s
-5 261 M
-( architecture of the SSH protocol, as well as the notation and) s
-5 250 M
-( terminology used in SSH protocol documents. It also discusses the SSH) s
-5 239 M
-( algorithm naming system that allows local extensions. The SSH) s
-5 228 M
-( protocol consists of three major components: The Transport Layer) s
-5 217 M
-( Protocol provides server authentication, confidentiality, and) s
-5 206 M
-( integrity with perfect forward secrecy. The User Authentication) s
-5 195 M
-( Protocol authenticates the client to the server. The Connection) s
-5 184 M
-( Protocol multiplexes the encrypted tunnel into several logical) s
-5 173 M
-( channels. Details of these protocols are described in separate) s
-5 129 M
-(Ylonen & Moffat Expires March 31, 2004 [Page 1]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 2 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Protocol Architecture Oct 2003) s
-5 690 M
-( documents.) s
-5 668 M
-(Table of Contents) s
-5 646 M
-( 1. Contributors . . . . . . . . . . . . . . . . . . . . . . . . 3) s
-5 635 M
-( 2. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3) s
-5 624 M
-( 3. Specification of Requirements . . . . . . . . . . . . . . . 3) s
-5 613 M
-( 4. Architecture . . . . . . . . . . . . . . . . . . . . . . . . 3) s
-5 602 M
-( 4.1 Host Keys . . . . . . . . . . . . . . . . . . . . . . . . . 4) s
-5 591 M
-( 4.2 Extensibility . . . . . . . . . . . . . . . . . . . . . . . 5) s
-5 580 M
-( 4.3 Policy Issues . . . . . . . . . . . . . . . . . . . . . . . 5) s
-5 569 M
-( 4.4 Security Properties . . . . . . . . . . . . . . . . . . . . 6) s
-5 558 M
-( 4.5 Packet Size and Overhead . . . . . . . . . . . . . . . . . . 6) s
-5 547 M
-( 4.6 Localization and Character Set Support . . . . . . . . . . . 7) s
-5 536 M
-( 5. Data Type Representations Used in the SSH Protocols . . . . 8) s
-5 525 M
-( 6. Algorithm Naming . . . . . . . . . . . . . . . . . . . . . . 10) s
-5 514 M
-( 7. Message Numbers . . . . . . . . . . . . . . . . . . . . . . 11) s
-5 503 M
-( 8. IANA Considerations . . . . . . . . . . . . . . . . . . . . 11) s
-5 492 M
-( 9. Security Considerations . . . . . . . . . . . . . . . . . . 12) s
-5 481 M
-( 9.1 Pseudo-Random Number Generation . . . . . . . . . . . . . . 12) s
-5 470 M
-( 9.2 Transport . . . . . . . . . . . . . . . . . . . . . . . . . 13) s
-5 459 M
-( 9.2.1 Confidentiality . . . . . . . . . . . . . . . . . . . . . . 13) s
-5 448 M
-( 9.2.2 Data Integrity . . . . . . . . . . . . . . . . . . . . . . . 16) s
-5 437 M
-( 9.2.3 Replay . . . . . . . . . . . . . . . . . . . . . . . . . . . 16) s
-5 426 M
-( 9.2.4 Man-in-the-middle . . . . . . . . . . . . . . . . . . . . . 17) s
-5 415 M
-( 9.2.5 Denial-of-service . . . . . . . . . . . . . . . . . . . . . 19) s
-5 404 M
-( 9.2.6 Covert Channels . . . . . . . . . . . . . . . . . . . . . . 19) s
-5 393 M
-( 9.2.7 Forward Secrecy . . . . . . . . . . . . . . . . . . . . . . 20) s
-5 382 M
-( 9.3 Authentication Protocol . . . . . . . . . . . . . . . . . . 20) s
-5 371 M
-( 9.3.1 Weak Transport . . . . . . . . . . . . . . . . . . . . . . . 21) s
-5 360 M
-( 9.3.2 Debug messages . . . . . . . . . . . . . . . . . . . . . . . 21) s
-5 349 M
-( 9.3.3 Local security policy . . . . . . . . . . . . . . . . . . . 21) s
-5 338 M
-( 9.3.4 Public key authentication . . . . . . . . . . . . . . . . . 22) s
-5 327 M
-( 9.3.5 Password authentication . . . . . . . . . . . . . . . . . . 22) s
-5 316 M
-( 9.3.6 Host based authentication . . . . . . . . . . . . . . . . . 23) s
-5 305 M
-( 9.4 Connection protocol . . . . . . . . . . . . . . . . . . . . 23) s
-5 294 M
-( 9.4.1 End point security . . . . . . . . . . . . . . . . . . . . . 23) s
-5 283 M
-( 9.4.2 Proxy forwarding . . . . . . . . . . . . . . . . . . . . . . 23) s
-5 272 M
-( 9.4.3 X11 forwarding . . . . . . . . . . . . . . . . . . . . . . . 24) s
-5 261 M
-( Normative References . . . . . . . . . . . . . . . . . . . . 24) s
-5 250 M
-( Informative References . . . . . . . . . . . . . . . . . . . 25) s
-5 239 M
-( Authors' Addresses . . . . . . . . . . . . . . . . . . . . . 27) s
-5 228 M
-( Intellectual Property and Copyright Statements . . . . . . . 28) s
-5 129 M
-(Ylonen & Moffat Expires March 31, 2004 [Page 2]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (2,3) 2
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 3 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Protocol Architecture Oct 2003) s
-5 690 M
-(1. Contributors) s
-5 668 M
-( The major original contributors of this document were: Tatu Ylonen,) s
-5 657 M
-( Tero Kivinen, Timo J. Rinne, Sami Lehtinen \(all of SSH Communications) s
-5 646 M
-( Security Corp\), and Markku-Juhani O. Saarinen \(University of) s
-5 635 M
-( Jyvaskyla\)) s
-5 613 M
-( The document editor is: [email protected]. Comments on this) s
-5 602 M
-( internet draft should be sent to the IETF SECSH working group,) s
-5 591 M
-( details at: http://ietf.org/html.charters/secsh-charter.html) s
-5 569 M
-(2. Introduction) s
-5 547 M
-( SSH is a protocol for secure remote login and other secure network) s
-5 536 M
-( services over an insecure network. It consists of three major) s
-5 525 M
-( components:) s
-5 514 M
-( o The Transport Layer Protocol [SSH-TRANS] provides server) s
-5 503 M
-( authentication, confidentiality, and integrity. It may optionally) s
-5 492 M
-( also provide compression. The transport layer will typically be) s
-5 481 M
-( run over a TCP/IP connection, but might also be used on top of any) s
-5 470 M
-( other reliable data stream.) s
-5 459 M
-( o The User Authentication Protocol [SSH-USERAUTH] authenticates the) s
-5 448 M
-( client-side user to the server. It runs over the transport layer) s
-5 437 M
-( protocol.) s
-5 426 M
-( o The Connection Protocol [SSH-CONNECT] multiplexes the encrypted) s
-5 415 M
-( tunnel into several logical channels. It runs over the user) s
-5 404 M
-( authentication protocol.) s
-5 382 M
-( The client sends a service request once a secure transport layer) s
-5 371 M
-( connection has been established. A second service request is sent) s
-5 360 M
-( after user authentication is complete. This allows new protocols to) s
-5 349 M
-( be defined and coexist with the protocols listed above.) s
-5 327 M
-( The connection protocol provides channels that can be used for a wide) s
-5 316 M
-( range of purposes. Standard methods are provided for setting up) s
-5 305 M
-( secure interactive shell sessions and for forwarding \("tunneling"\)) s
-5 294 M
-( arbitrary TCP/IP ports and X11 connections.) s
-5 272 M
-(3. Specification of Requirements) s
-5 250 M
-( All documents related to the SSH protocols shall use the keywords) s
-5 239 M
-( "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD",) s
-5 228 M
-( "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" to describe) s
-5 217 M
-( requirements. They are to be interpreted as described in [RFC2119].) s
-5 195 M
-(4. Architecture) s
-5 129 M
-(Ylonen & Moffat Expires March 31, 2004 [Page 3]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 4 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Protocol Architecture Oct 2003) s
-5 690 M
-(4.1 Host Keys) s
-5 668 M
-( Each server host SHOULD have a host key. Hosts MAY have multiple) s
-5 657 M
-( host keys using multiple different algorithms. Multiple hosts MAY) s
-5 646 M
-( share the same host key. If a host has keys at all, it MUST have at) s
-5 635 M
-( least one key using each REQUIRED public key algorithm \(DSS) s
-5 624 M
-( [FIPS-186]\).) s
-5 602 M
-( The server host key is used during key exchange to verify that the) s
-5 591 M
-( client is really talking to the correct server. For this to be) s
-5 580 M
-( possible, the client must have a priori knowledge of the server's) s
-5 569 M
-( public host key.) s
-5 547 M
-( Two different trust models can be used:) s
-5 536 M
-( o The client has a local database that associates each host name \(as) s
-5 525 M
-( typed by the user\) with the corresponding public host key. This) s
-5 514 M
-( method requires no centrally administered infrastructure, and no) s
-5 503 M
-( third-party coordination. The downside is that the database of) s
-5 492 M
-( name-to-key associations may become burdensome to maintain.) s
-5 481 M
-( o The host name-to-key association is certified by some trusted) s
-5 470 M
-( certification authority. The client only knows the CA root key,) s
-5 459 M
-( and can verify the validity of all host keys certified by accepted) s
-5 448 M
-( CAs.) s
-5 426 M
-( The second alternative eases the maintenance problem, since) s
-5 415 M
-( ideally only a single CA key needs to be securely stored on the) s
-5 404 M
-( client. On the other hand, each host key must be appropriately) s
-5 393 M
-( certified by a central authority before authorization is possible.) s
-5 382 M
-( Also, a lot of trust is placed on the central infrastructure.) s
-5 360 M
-( The protocol provides the option that the server name - host key) s
-5 349 M
-( association is not checked when connecting to the host for the first) s
-5 338 M
-( time. This allows communication without prior communication of host) s
-5 327 M
-( keys or certification. The connection still provides protection) s
-5 316 M
-( against passive listening; however, it becomes vulnerable to active) s
-5 305 M
-( man-in-the-middle attacks. Implementations SHOULD NOT normally allow) s
-5 294 M
-( such connections by default, as they pose a potential security) s
-5 283 M
-( problem. However, as there is no widely deployed key infrastructure) s
-5 272 M
-( available on the Internet yet, this option makes the protocol much) s
-5 261 M
-( more usable during the transition time until such an infrastructure) s
-5 250 M
-( emerges, while still providing a much higher level of security than) s
-5 239 M
-( that offered by older solutions \(e.g. telnet [RFC-854] and rlogin) s
-5 228 M
-( [RFC-1282]\).) s
-5 206 M
-( Implementations SHOULD try to make the best effort to check host) s
-5 195 M
-( keys. An example of a possible strategy is to only accept a host key) s
-5 184 M
-( without checking the first time a host is connected, save the key in) s
-5 173 M
-( a local database, and compare against that key on all future) s
-5 129 M
-(Ylonen & Moffat Expires March 31, 2004 [Page 4]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (4,5) 3
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 5 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Protocol Architecture Oct 2003) s
-5 690 M
-( connections to that host.) s
-5 668 M
-( Implementations MAY provide additional methods for verifying the) s
-5 657 M
-( correctness of host keys, e.g. a hexadecimal fingerprint derived from) s
-5 646 M
-( the SHA-1 hash of the public key. Such fingerprints can easily be) s
-5 635 M
-( verified by using telephone or other external communication channels.) s
-5 613 M
-( All implementations SHOULD provide an option to not accept host keys) s
-5 602 M
-( that cannot be verified.) s
-5 580 M
-( We believe that ease of use is critical to end-user acceptance of) s
-5 569 M
-( security solutions, and no improvement in security is gained if the) s
-5 558 M
-( new solutions are not used. Thus, providing the option not to check) s
-5 547 M
-( the server host key is believed to improve the overall security of) s
-5 536 M
-( the Internet, even though it reduces the security of the protocol in) s
-5 525 M
-( configurations where it is allowed.) s
-5 503 M
-(4.2 Extensibility) s
-5 481 M
-( We believe that the protocol will evolve over time, and some) s
-5 470 M
-( organizations will want to use their own encryption, authentication) s
-5 459 M
-( and/or key exchange methods. Central registration of all extensions) s
-5 448 M
-( is cumbersome, especially for experimental or classified features.) s
-5 437 M
-( On the other hand, having no central registration leads to conflicts) s
-5 426 M
-( in method identifiers, making interoperability difficult.) s
-5 404 M
-( We have chosen to identify algorithms, methods, formats, and) s
-5 393 M
-( extension protocols with textual names that are of a specific format.) s
-5 382 M
-( DNS names are used to create local namespaces where experimental or) s
-5 371 M
-( classified extensions can be defined without fear of conflicts with) s
-5 360 M
-( other implementations.) s
-5 338 M
-( One design goal has been to keep the base protocol as simple as) s
-5 327 M
-( possible, and to require as few algorithms as possible. However, all) s
-5 316 M
-( implementations MUST support a minimal set of algorithms to ensure) s
-5 305 M
-( interoperability \(this does not imply that the local policy on all) s
-5 294 M
-( hosts would necessary allow these algorithms\). The mandatory) s
-5 283 M
-( algorithms are specified in the relevant protocol documents.) s
-5 261 M
-( Additional algorithms, methods, formats, and extension protocols can) s
-5 250 M
-( be defined in separate drafts. See Section Algorithm Naming \(Section) s
-5 239 M
-( 6\) for more information.) s
-5 217 M
-(4.3 Policy Issues) s
-5 195 M
-( The protocol allows full negotiation of encryption, integrity, key) s
-5 184 M
-( exchange, compression, and public key algorithms and formats.) s
-5 173 M
-( Encryption, integrity, public key, and compression algorithms can be) s
-5 129 M
-(Ylonen & Moffat Expires March 31, 2004 [Page 5]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 6 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Protocol Architecture Oct 2003) s
-5 690 M
-( different for each direction.) s
-5 668 M
-( The following policy issues SHOULD be addressed in the configuration) s
-5 657 M
-( mechanisms of each implementation:) s
-5 646 M
-( o Encryption, integrity, and compression algorithms, separately for) s
-5 635 M
-( each direction. The policy MUST specify which is the preferred) s
-5 624 M
-( algorithm \(e.g. the first algorithm listed in each category\).) s
-5 613 M
-( o Public key algorithms and key exchange method to be used for host) s
-5 602 M
-( authentication. The existence of trusted host keys for different) s
-5 591 M
-( public key algorithms also affects this choice.) s
-5 580 M
-( o The authentication methods that are to be required by the server) s
-5 569 M
-( for each user. The server's policy MAY require multiple) s
-5 558 M
-( authentication for some or all users. The required algorithms MAY) s
-5 547 M
-( depend on the location where the user is trying to log in from.) s
-5 536 M
-( o The operations that the user is allowed to perform using the) s
-5 525 M
-( connection protocol. Some issues are related to security; for) s
-5 514 M
-( example, the policy SHOULD NOT allow the server to start sessions) s
-5 503 M
-( or run commands on the client machine, and MUST NOT allow) s
-5 492 M
-( connections to the authentication agent unless forwarding such) s
-5 481 M
-( connections has been requested. Other issues, such as which TCP/) s
-5 470 M
-( IP ports can be forwarded and by whom, are clearly issues of local) s
-5 459 M
-( policy. Many of these issues may involve traversing or bypassing) s
-5 448 M
-( firewalls, and are interrelated with the local security policy.) s
-5 426 M
-(4.4 Security Properties) s
-5 404 M
-( The primary goal of the SSH protocol is improved security on the) s
-5 393 M
-( Internet. It attempts to do this in a way that is easy to deploy,) s
-5 382 M
-( even at the cost of absolute security.) s
-5 371 M
-( o All encryption, integrity, and public key algorithms used are) s
-5 360 M
-( well-known, well-established algorithms.) s
-5 349 M
-( o All algorithms are used with cryptographically sound key sizes) s
-5 338 M
-( that are believed to provide protection against even the strongest) s
-5 327 M
-( cryptanalytic attacks for decades.) s
-5 316 M
-( o All algorithms are negotiated, and in case some algorithm is) s
-5 305 M
-( broken, it is easy to switch to some other algorithm without) s
-5 294 M
-( modifying the base protocol.) s
-5 272 M
-( Specific concessions were made to make wide-spread fast deployment) s
-5 261 M
-( easier. The particular case where this comes up is verifying that) s
-5 250 M
-( the server host key really belongs to the desired host; the protocol) s
-5 239 M
-( allows the verification to be left out \(but this is NOT RECOMMENDED\).) s
-5 228 M
-( This is believed to significantly improve usability in the short) s
-5 217 M
-( term, until widespread Internet public key infrastructures emerge.) s
-5 195 M
-(4.5 Packet Size and Overhead) s
-5 173 M
-( Some readers will worry about the increase in packet size due to new) s
-5 129 M
-(Ylonen & Moffat Expires March 31, 2004 [Page 6]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (6,7) 4
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 7 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Protocol Architecture Oct 2003) s
-5 690 M
-( headers, padding, and MAC. The minimum packet size is in the order) s
-5 679 M
-( of 28 bytes \(depending on negotiated algorithms\). The increase is) s
-5 668 M
-( negligible for large packets, but very significant for one-byte) s
-5 657 M
-( packets \(telnet-type sessions\). There are, however, several factors) s
-5 646 M
-( that make this a non-issue in almost all cases:) s
-5 635 M
-( o The minimum size of a TCP/IP header is 32 bytes. Thus, the) s
-5 624 M
-( increase is actually from 33 to 51 bytes \(roughly\).) s
-5 613 M
-( o The minimum size of the data field of an Ethernet packet is 46) s
-5 602 M
-( bytes [RFC-894]. Thus, the increase is no more than 5 bytes. When) s
-5 591 M
-( Ethernet headers are considered, the increase is less than 10) s
-5 580 M
-( percent.) s
-5 569 M
-( o The total fraction of telnet-type data in the Internet is) s
-5 558 M
-( negligible, even with increased packet sizes.) s
-5 536 M
-( The only environment where the packet size increase is likely to have) s
-5 525 M
-( a significant effect is PPP [RFC-1134] over slow modem lines \(PPP) s
-5 514 M
-( compresses the TCP/IP headers, emphasizing the increase in packet) s
-5 503 M
-( size\). However, with modern modems, the time needed to transfer is in) s
-5 492 M
-( the order of 2 milliseconds, which is a lot faster than people can) s
-5 481 M
-( type.) s
-5 459 M
-( There are also issues related to the maximum packet size. To) s
-5 448 M
-( minimize delays in screen updates, one does not want excessively) s
-5 437 M
-( large packets for interactive sessions. The maximum packet size is) s
-5 426 M
-( negotiated separately for each channel.) s
-5 404 M
-(4.6 Localization and Character Set Support) s
-5 382 M
-( For the most part, the SSH protocols do not directly pass text that) s
-5 371 M
-( would be displayed to the user. However, there are some places where) s
-5 360 M
-( such data might be passed. When applicable, the character set for the) s
-5 349 M
-( data MUST be explicitly specified. In most places, ISO 10646 with) s
-5 338 M
-( UTF-8 encoding is used [RFC-2279]. When applicable, a field is also) s
-5 327 M
-( provided for a language tag [RFC-3066].) s
-5 305 M
-( One big issue is the character set of the interactive session. There) s
-5 294 M
-( is no clear solution, as different applications may display data in) s
-5 283 M
-( different formats. Different types of terminal emulation may also be) s
-5 272 M
-( employed in the client, and the character set to be used is) s
-5 261 M
-( effectively determined by the terminal emulation. Thus, no place is) s
-5 250 M
-( provided for directly specifying the character set or encoding for) s
-5 239 M
-( terminal session data. However, the terminal emulation type \(e.g.) s
-5 228 M
-( "vt100"\) is transmitted to the remote site, and it implicitly) s
-5 217 M
-( specifies the character set and encoding. Applications typically use) s
-5 206 M
-( the terminal type to determine what character set they use, or the) s
-5 195 M
-( character set is determined using some external means. The terminal) s
-5 184 M
-( emulation may also allow configuring the default character set. In) s
-5 173 M
-( any case, the character set for the terminal session is considered) s
-5 129 M
-(Ylonen & Moffat Expires March 31, 2004 [Page 7]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 8 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Protocol Architecture Oct 2003) s
-5 690 M
-( primarily a client local issue.) s
-5 668 M
-( Internal names used to identify algorithms or protocols are normally) s
-5 657 M
-( never displayed to users, and must be in US-ASCII.) s
-5 635 M
-( The client and server user names are inherently constrained by what) s
-5 624 M
-( the server is prepared to accept. They might, however, occasionally) s
-5 613 M
-( be displayed in logs, reports, etc. They MUST be encoded using ISO) s
-5 602 M
-( 10646 UTF-8, but other encodings may be required in some cases. It) s
-5 591 M
-( is up to the server to decide how to map user names to accepted user) s
-5 580 M
-( names. Straight bit-wise binary comparison is RECOMMENDED.) s
-5 558 M
-( For localization purposes, the protocol attempts to minimize the) s
-5 547 M
-( number of textual messages transmitted. When present, such messages) s
-5 536 M
-( typically relate to errors, debugging information, or some externally) s
-5 525 M
-( configured data. For data that is normally displayed, it SHOULD be) s
-5 514 M
-( possible to fetch a localized message instead of the transmitted) s
-5 503 M
-( message by using a numerical code. The remaining messages SHOULD be) s
-5 492 M
-( configurable.) s
-5 470 M
-(5. Data Type Representations Used in the SSH Protocols) s
-5 459 M
-( byte) s
-5 437 M
-( A byte represents an arbitrary 8-bit value \(octet\) [RFC-1700].) s
-5 426 M
-( Fixed length data is sometimes represented as an array of bytes,) s
-5 415 M
-( written byte[n], where n is the number of bytes in the array.) s
-5 393 M
-( boolean) s
-5 371 M
-( A boolean value is stored as a single byte. The value 0) s
-5 360 M
-( represents FALSE, and the value 1 represents TRUE. All non-zero) s
-5 349 M
-( values MUST be interpreted as TRUE; however, applications MUST NOT) s
-5 338 M
-( store values other than 0 and 1.) s
-5 316 M
-( uint32) s
-5 294 M
-( Represents a 32-bit unsigned integer. Stored as four bytes in the) s
-5 283 M
-( order of decreasing significance \(network byte order\). For) s
-5 272 M
-( example, the value 699921578 \(0x29b7f4aa\) is stored as 29 b7 f4) s
-5 261 M
-( aa.) s
-5 239 M
-( uint64) s
-5 217 M
-( Represents a 64-bit unsigned integer. Stored as eight bytes in) s
-5 206 M
-( the order of decreasing significance \(network byte order\).) s
-5 129 M
-(Ylonen & Moffat Expires March 31, 2004 [Page 8]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (8,9) 5
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 9 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Protocol Architecture Oct 2003) s
-5 690 M
-( string) s
-5 668 M
-( Arbitrary length binary string. Strings are allowed to contain) s
-5 657 M
-( arbitrary binary data, including null characters and 8-bit) s
-5 646 M
-( characters. They are stored as a uint32 containing its length) s
-5 635 M
-( \(number of bytes that follow\) and zero \(= empty string\) or more) s
-5 624 M
-( bytes that are the value of the string. Terminating null) s
-5 613 M
-( characters are not used.) s
-5 591 M
-( Strings are also used to store text. In that case, US-ASCII is) s
-5 580 M
-( used for internal names, and ISO-10646 UTF-8 for text that might) s
-5 569 M
-( be displayed to the user. The terminating null character SHOULD) s
-5 558 M
-( NOT normally be stored in the string.) s
-5 536 M
-( For example, the US-ASCII string "testing" is represented as 00 00) s
-5 525 M
-( 00 07 t e s t i n g. The UTF8 mapping does not alter the encoding) s
-5 514 M
-( of US-ASCII characters.) s
-5 492 M
-( mpint) s
-5 470 M
-( Represents multiple precision integers in two's complement format,) s
-5 459 M
-( stored as a string, 8 bits per byte, MSB first. Negative numbers) s
-5 448 M
-( have the value 1 as the most significant bit of the first byte of) s
-5 437 M
-( the data partition. If the most significant bit would be set for a) s
-5 426 M
-( positive number, the number MUST be preceded by a zero byte.) s
-5 415 M
-( Unnecessary leading bytes with the value 0 or 255 MUST NOT be) s
-5 404 M
-( included. The value zero MUST be stored as a string with zero) s
-5 393 M
-( bytes of data.) s
-5 371 M
-( By convention, a number that is used in modular computations in) s
-5 360 M
-( Z_n SHOULD be represented in the range 0 <= x < n.) s
-5 338 M
-( Examples:) s
-5 327 M
-( value \(hex\) representation \(hex\)) s
-5 316 M
-( ---------------------------------------------------------------) s
-5 305 M
-( 0 00 00 00 00) s
-5 294 M
-( 9a378f9b2e332a7 00 00 00 08 09 a3 78 f9 b2 e3 32 a7) s
-5 283 M
-( 80 00 00 00 02 00 80) s
-5 272 M
-( -1234 00 00 00 02 ed cc) s
-5 261 M
-( -deadbeef 00 00 00 05 ff 21 52 41 11) s
-5 217 M
-( name-list) s
-5 195 M
-( A string containing a comma separated list of names. A name list) s
-5 184 M
-( is represented as a uint32 containing its length \(number of bytes) s
-5 173 M
-( that follow\) followed by a comma-separated list of zero or more) s
-5 129 M
-(Ylonen & Moffat Expires March 31, 2004 [Page 9]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 10 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Protocol Architecture Oct 2003) s
-5 690 M
-( names. A name MUST be non-zero length, and it MUST NOT contain a) s
-5 679 M
-( comma \(','\). Context may impose additional restrictions on the) s
-5 668 M
-( names; for example, the names in a list may have to be valid) s
-5 657 M
-( algorithm identifier \(see Algorithm Naming below\), or [RFC-3066]) s
-5 646 M
-( language tags. The order of the names in a list may or may not be) s
-5 635 M
-( significant, also depending on the context where the list is is) s
-5 624 M
-( used. Terminating NUL characters are not used, neither for the) s
-5 613 M
-( individual names, nor for the list as a whole.) s
-5 591 M
-( Examples:) s
-5 580 M
-( value representation \(hex\)) s
-5 569 M
-( ---------------------------------------) s
-5 558 M
-( \(\), the empty list 00 00 00 00) s
-5 547 M
-( \("zlib"\) 00 00 00 04 7a 6c 69 62) s
-5 536 M
-( \("zlib", "none"\) 00 00 00 09 7a 6c 69 62 2c 6e 6f 6e 65) s
-5 481 M
-(6. Algorithm Naming) s
-5 459 M
-( The SSH protocols refer to particular hash, encryption, integrity,) s
-5 448 M
-( compression, and key exchange algorithms or protocols by names.) s
-5 437 M
-( There are some standard algorithms that all implementations MUST) s
-5 426 M
-( support. There are also algorithms that are defined in the protocol) s
-5 415 M
-( specification but are OPTIONAL. Furthermore, it is expected that) s
-5 404 M
-( some organizations will want to use their own algorithms.) s
-5 382 M
-( In this protocol, all algorithm identifiers MUST be printable) s
-5 371 M
-( US-ASCII non-empty strings no longer than 64 characters. Names MUST) s
-5 360 M
-( be case-sensitive.) s
-5 338 M
-( There are two formats for algorithm names:) s
-5 327 M
-( o Names that do not contain an at-sign \(@\) are reserved to be) s
-5 316 M
-( assigned by IETF consensus \(RFCs\). Examples include `3des-cbc',) s
-5 305 M
-( `sha-1', `hmac-sha1', and `zlib' \(the quotes are not part of the) s
-5 294 M
-( name\). Names of this format MUST NOT be used without first) s
-5 283 M
-( registering them. Registered names MUST NOT contain an at-sign) s
-5 272 M
-( \(@\) or a comma \(,\).) s
-5 261 M
-( o Anyone can define additional algorithms by using names in the) s
-5 250 M
-( format name@domainname, e.g. "[email protected]". The) s
-5 239 M
-( format of the part preceding the at sign is not specified; it MUST) s
-5 228 M
-( consist of US-ASCII characters except at-sign and comma. The part) s
-5 217 M
-( following the at-sign MUST be a valid fully qualified internet) s
-5 206 M
-( domain name [RFC-1034] controlled by the person or organization) s
-5 195 M
-( defining the name. It is up to each domain how it manages its) s
-5 184 M
-( local namespace.) s
-5 129 M
-(Ylonen & Moffat Expires March 31, 2004 [Page 10]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (10,11) 6
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 11 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Protocol Architecture Oct 2003) s
-5 690 M
-(7. Message Numbers) s
-5 668 M
-( SSH packets have message numbers in the range 1 to 255. These numbers) s
-5 657 M
-( have been allocated as follows:) s
-5 624 M
-( Transport layer protocol:) s
-5 602 M
-( 1 to 19 Transport layer generic \(e.g. disconnect, ignore, debug,) s
-5 591 M
-( etc.\)) s
-5 580 M
-( 20 to 29 Algorithm negotiation) s
-5 569 M
-( 30 to 49 Key exchange method specific \(numbers can be reused for) s
-5 558 M
-( different authentication methods\)) s
-5 536 M
-( User authentication protocol:) s
-5 514 M
-( 50 to 59 User authentication generic) s
-5 503 M
-( 60 to 79 User authentication method specific \(numbers can be) s
-5 492 M
-( reused for different authentication methods\)) s
-5 470 M
-( Connection protocol:) s
-5 448 M
-( 80 to 89 Connection protocol generic) s
-5 437 M
-( 90 to 127 Channel related messages) s
-5 415 M
-( Reserved for client protocols:) s
-5 393 M
-( 128 to 191 Reserved) s
-5 371 M
-( Local extensions:) s
-5 349 M
-( 192 to 255 Local extensions) s
-5 305 M
-(8. IANA Considerations) s
-5 283 M
-( The initial state of the IANA registry is detailed in [SSH-NUMBERS].) s
-5 261 M
-( Allocation of the following types of names in the SSH protocols is) s
-5 250 M
-( assigned by IETF consensus:) s
-5 239 M
-( o SSH encryption algorithm names,) s
-5 228 M
-( o SSH MAC algorithm names,) s
-5 217 M
-( o SSH public key algorithm names \(public key algorithm also implies) s
-5 206 M
-( encoding and signature/encryption capability\),) s
-5 195 M
-( o SSH key exchange method names, and) s
-5 184 M
-( o SSH protocol \(service\) names.) s
-5 129 M
-(Ylonen & Moffat Expires March 31, 2004 [Page 11]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 12 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Protocol Architecture Oct 2003) s
-5 690 M
-( These names MUST be printable US-ASCII strings, and MUST NOT contain) s
-5 679 M
-( the characters at-sign \('@'\), comma \(','\), or whitespace or control) s
-5 668 M
-( characters \(ASCII codes 32 or less\). Names are case-sensitive, and) s
-5 657 M
-( MUST NOT be longer than 64 characters.) s
-5 635 M
-( Names with the at-sign \('@'\) in them are allocated by the owner of) s
-5 624 M
-( DNS name after the at-sign \(hierarchical allocation in [RFC-2343]\),) s
-5 613 M
-( otherwise the same restrictions as above.) s
-5 591 M
-( Each category of names listed above has a separate namespace.) s
-5 580 M
-( However, using the same name in multiple categories SHOULD be avoided) s
-5 569 M
-( to minimize confusion.) s
-5 547 M
-( Message numbers \(see Section Message Numbers \(Section 7\)\) in the) s
-5 536 M
-( range of 0..191 are allocated via IETF consensus; message numbers in) s
-5 525 M
-( the 192..255 range \(the "Local extensions" set\) are reserved for) s
-5 514 M
-( private use.) s
-5 492 M
-(9. Security Considerations) s
-5 470 M
-( In order to make the entire body of Security Considerations more) s
-5 459 M
-( accessible, Security Considerations for the transport,) s
-5 448 M
-( authentication, and connection documents have been gathered here.) s
-5 426 M
-( The transport protocol [1] provides a confidential channel over an) s
-5 415 M
-( insecure network. It performs server host authentication, key) s
-5 404 M
-( exchange, encryption, and integrity protection. It also derives a) s
-5 393 M
-( unique session id that may be used by higher-level protocols.) s
-5 371 M
-( The authentication protocol [2] provides a suite of mechanisms which) s
-5 360 M
-( can be used to authenticate the client user to the server.) s
-5 349 M
-( Individual mechanisms specified in the in authentication protocol use) s
-5 338 M
-( the session id provided by the transport protocol and/or depend on) s
-5 327 M
-( the security and integrity guarantees of the transport protocol.) s
-5 305 M
-( The connection protocol [3] specifies a mechanism to multiplex) s
-5 294 M
-( multiple streams [channels] of data over the confidential and) s
-5 283 M
-( authenticated transport. It also specifies channels for accessing an) s
-5 272 M
-( interactive shell, for 'proxy-forwarding' various external protocols) s
-5 261 M
-( over the secure transport \(including arbitrary TCP/IP protocols\), and) s
-5 250 M
-( for accessing secure 'subsystems' on the server host.) s
-5 228 M
-(9.1 Pseudo-Random Number Generation) s
-5 206 M
-( This protocol binds each session key to the session by including) s
-5 195 M
-( random, session specific data in the hash used to produce session) s
-5 184 M
-( keys. Special care should be taken to ensure that all of the random) s
-5 173 M
-( numbers are of good quality. If the random data here \(e.g., DH) s
-5 129 M
-(Ylonen & Moffat Expires March 31, 2004 [Page 12]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (12,13) 7
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 13 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Protocol Architecture Oct 2003) s
-5 690 M
-( parameters\) are pseudo-random then the pseudo-random number generator) s
-5 679 M
-( should be cryptographically secure \(i.e., its next output not easily) s
-5 668 M
-( guessed even when knowing all previous outputs\) and, furthermore,) s
-5 657 M
-( proper entropy needs to be added to the pseudo-random number) s
-5 646 M
-( generator. RFC 1750 [1750] offers suggestions for sources of random) s
-5 635 M
-( numbers and entropy. Implementors should note the importance of) s
-5 624 M
-( entropy and the well-meant, anecdotal warning about the difficulty in) s
-5 613 M
-( properly implementing pseudo-random number generating functions.) s
-5 591 M
-( The amount of entropy available to a given client or server may) s
-5 580 M
-( sometimes be less than what is required. In this case one must) s
-5 569 M
-( either resort to pseudo-random number generation regardless of) s
-5 558 M
-( insufficient entropy or refuse to run the protocol. The latter is) s
-5 547 M
-( preferable.) s
-5 525 M
-(9.2 Transport) s
-5 503 M
-(9.2.1 Confidentiality) s
-5 481 M
-( It is beyond the scope of this document and the Secure Shell Working) s
-5 470 M
-( Group to analyze or recommend specific ciphers other than the ones) s
-5 459 M
-( which have been established and accepted within the industry. At the) s
-5 448 M
-( time of this writing, ciphers commonly in use include 3DES, ARCFOUR,) s
-5 437 M
-( twofish, serpent and blowfish. AES has been accepted by The) s
-5 426 M
-( published as a US Federal Information Processing Standards [FIPS-197]) s
-5 415 M
-( and the cryptographic community as being acceptable for this purpose) s
-5 404 M
-( as well has accepted AES. As always, implementors and users should) s
-5 393 M
-( check current literature to ensure that no recent vulnerabilities) s
-5 382 M
-( have been found in ciphers used within products. Implementors should) s
-5 371 M
-( also check to see which ciphers are considered to be relatively) s
-5 360 M
-( stronger than others and should recommend their use to users over) s
-5 349 M
-( relatively weaker ciphers. It would be considered good form for an) s
-5 338 M
-( implementation to politely and unobtrusively notify a user that a) s
-5 327 M
-( stronger cipher is available and should be used when a weaker one is) s
-5 316 M
-( actively chosen.) s
-5 294 M
-( The "none" cipher is provided for debugging and SHOULD NOT be used) s
-5 283 M
-( except for that purpose. It's cryptographic properties are) s
-5 272 M
-( sufficiently described in RFC 2410, which will show that its use does) s
-5 261 M
-( not meet the intent of this protocol.) s
-5 239 M
-( The relative merits of these and other ciphers may also be found in) s
-5 228 M
-( current literature. Two references that may provide information on) s
-5 217 M
-( the subject are [SCHNEIER] and [KAUFMAN,PERLMAN,SPECINER]. Both of) s
-5 206 M
-( these describe the CBC mode of operation of certain ciphers and the) s
-5 195 M
-( weakness of this scheme. Essentially, this mode is theoretically) s
-5 184 M
-( vulnerable to chosen cipher-text attacks because of the high) s
-5 173 M
-( predictability of the start of packet sequence. However, this attack) s
-5 129 M
-(Ylonen & Moffat Expires March 31, 2004 [Page 13]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 14 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Protocol Architecture Oct 2003) s
-5 690 M
-( is still deemed difficult and not considered fully practicable) s
-5 679 M
-( especially if relatively longer block sizes are used.) s
-5 657 M
-( Additionally, another CBC mode attack may be mitigated through the) s
-5 646 M
-( insertion of packets containing SSH_MSG_IGNORE. Without this) s
-5 635 M
-( technique, a specific attack may be successful. For this attack) s
-5 624 M
-( \(commonly known as the Rogaway attack) s
-5 613 M
-( [ROGAWAY],[DAI],[BELLARE,KOHNO,NAMPREMPRE]\) to work, the attacker) s
-5 602 M
-( would need to know the IV of the next block that is going to be) s
-5 591 M
-( encrypted. In CBC mode that is the output of the encryption of the) s
-5 580 M
-( previous block. If the attacker does not have any way to see the) s
-5 569 M
-( packet yet \(i.e it is in the internal buffers of the ssh) s
-5 558 M
-( implementation or even in the kernel\) then this attack will not work.) s
-5 547 M
-( If the last packet has been sent out to the network \(i.e the attacker) s
-5 536 M
-( has access to it\) then he can use the attack.) s
-5 514 M
-( In the optimal case an implementor would need to add an extra packet) s
-5 503 M
-( only if the packet has been sent out onto the network and there are) s
-5 492 M
-( no other packets waiting for transmission. Implementors may wish to) s
-5 481 M
-( check to see if there are any unsent packets awaiting transmission,) s
-5 470 M
-( but unfortunately it is not normally easy to obtain this information) s
-5 459 M
-( from the kernel or buffers. If there are not, then a packet) s
-5 448 M
-( containing SSH_MSG_IGNORE SHOULD be sent. If a new packet is added) s
-5 437 M
-( to the stream every time the attacker knows the IV that is supposed) s
-5 426 M
-( to be used for the next packet, then the attacker will not be able to) s
-5 415 M
-( guess the correct IV, thus the attack will never be successfull.) s
-5 393 M
-( As an example, consider the following case:) s
-5 360 M
-( Client Server) s
-5 349 M
-( ------ ------) s
-5 338 M
-( TCP\(seq=x, len=500\) ->) s
-5 327 M
-( contains Record 1) s
-5 305 M
-( [500 ms passes, no ACK]) s
-5 283 M
-( TCP\(seq=x, len=1000\) ->) s
-5 272 M
-( contains Records 1,2) s
-5 250 M
-( ACK) s
-5 217 M
-( 1. The Nagle algorithm + TCP retransmits mean that the two records) s
-5 206 M
-( get coalesced into a single TCP segment) s
-5 195 M
-( 2. Record 2 is *not* at the beginning of the TCP segment and never) s
-5 184 M
-( will be, since it gets ACKed.) s
-5 129 M
-(Ylonen & Moffat Expires March 31, 2004 [Page 14]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (14,15) 8
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 15 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Protocol Architecture Oct 2003) s
-5 690 M
-( 3. Yet, the attack is possible because Record 1 has already been) s
-5 679 M
-( seen.) s
-5 657 M
-( As this example indicates, it's totally unsafe to use the existence) s
-5 646 M
-( of unflushed data in the TCP buffers proper as a guide to whether you) s
-5 635 M
-( need an empty packet, since when you do the second write\(\), the) s
-5 624 M
-( buffers will contain the un-ACKed Record 1.) s
-5 129 M
-(Ylonen & Moffat Expires March 31, 2004 [Page 15]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 16 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Protocol Architecture Oct 2003) s
-5 690 M
-( On the other hand, it's perfectly safe to have the following) s
-5 679 M
-( situation:) s
-5 646 M
-( Client Server) s
-5 635 M
-( ------ ------) s
-5 624 M
-( TCP\(seq=x, len=500\) ->) s
-5 613 M
-( contains SSH_MSG_IGNORE) s
-5 591 M
-( TCP\(seq=y, len=500\) ->) s
-5 580 M
-( contains Data) s
-5 558 M
-( Provided that the IV for second SSH Record is fixed after the data for) s
-5 547 M
-( the Data packet is determined -i.e. you do:) s
-5 536 M
-( read from user) s
-5 525 M
-( encrypt null packet) s
-5 514 M
-( encrypt data packet) s
-5 481 M
-(9.2.2 Data Integrity) s
-5 459 M
-( This protocol does allow the Data Integrity mechanism to be disabled.) s
-5 448 M
-( Implementors SHOULD be wary of exposing this feature for any purpose) s
-5 437 M
-( other than debugging. Users and administrators SHOULD be explicitly) s
-5 426 M
-( warned anytime the "none" MAC is enabled.) s
-5 404 M
-( So long as the "none" MAC is not used, this protocol provides data) s
-5 393 M
-( integrity.) s
-5 371 M
-( Because MACs use a 32 bit sequence number, they might start to leak) s
-5 360 M
-( information after 2**32 packets have been sent. However, following) s
-5 349 M
-( the rekeying recommendations should prevent this attack. The) s
-5 338 M
-( transport protocol [1] recommends rekeying after one gigabyte of) s
-5 327 M
-( data, and the smallest possible packet is 16 bytes. Therefore,) s
-5 316 M
-( rekeying SHOULD happen after 2**28 packets at the very most.) s
-5 294 M
-(9.2.3 Replay) s
-5 272 M
-( The use of a MAC other than 'none' provides integrity and) s
-5 261 M
-( authentication. In addition, the transport protocol provides a) s
-5 250 M
-( unique session identifier \(bound in part to pseudo-random data that) s
-5 239 M
-( is part of the algorithm and key exchange process\) that can be used) s
-5 228 M
-( by higher level protocols to bind data to a given session and prevent) s
-5 217 M
-( replay of data from prior sessions. For example, the authentication) s
-5 206 M
-( protocol uses this to prevent replay of signatures from previous) s
-5 195 M
-( sessions. Because public key authentication exchanges are) s
-5 184 M
-( cryptographically bound to the session \(i.e., to the initial key) s
-5 173 M
-( exchange\) they cannot be successfully replayed in other sessions.) s
-5 129 M
-(Ylonen & Moffat Expires March 31, 2004 [Page 16]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (16,17) 9
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 17 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Protocol Architecture Oct 2003) s
-5 690 M
-( Note that the session ID can be made public without harming the) s
-5 679 M
-( security of the protocol.) s
-5 657 M
-( If two session happen to have the same session ID [hash of key) s
-5 646 M
-( exchanges] then packets from one can be replayed against the other.) s
-5 635 M
-( It must be stressed that the chances of such an occurrence are,) s
-5 624 M
-( needless to say, minimal when using modern cryptographic methods.) s
-5 613 M
-( This is all the more so true when specifying larger hash function) s
-5 602 M
-( outputs and DH parameters.) s
-5 580 M
-( Replay detection using monotonically increasing sequence numbers as) s
-5 569 M
-( input to the MAC, or HMAC in some cases, is described in [RFC2085] />) s
-5 558 M
-( [RFC2246], [RFC2743], [RFC1964], [RFC2025], and [RFC1510]. The) s
-5 547 M
-( underlying construct is discussed in [RFC2104]. Essentially a) s
-5 536 M
-( different sequence number in each packet ensures that at least this) s
-5 525 M
-( one input to the MAC function will be unique and will provide a) s
-5 514 M
-( nonrecurring MAC output that is not predictable to an attacker. If) s
-5 503 M
-( the session stays active long enough, however, this sequence number) s
-5 492 M
-( will wrap. This event may provide an attacker an opportunity to) s
-5 481 M
-( replay a previously recorded packet with an identical sequence number) s
-5 470 M
-( but only if the peers have not rekeyed since the transmission of the) s
-5 459 M
-( first packet with that sequence number. If the peers have rekeyed,) s
-5 448 M
-( then the replay will be detected as the MAC check will fail. For) s
-5 437 M
-( this reason, it must be emphasized that peers MUST rekey before a) s
-5 426 M
-( wrap of the sequence numbers. Naturally, if an attacker does attempt) s
-5 415 M
-( to replay a captured packet before the peers have rekeyed, then the) s
-5 404 M
-( receiver of the duplicate packet will not be able to validate the MAC) s
-5 393 M
-( and it will be discarded. The reason that the MAC will fail is) s
-5 382 M
-( because the receiver will formulate a MAC based upon the packet) s
-5 371 M
-( contents, the shared secret, and the expected sequence number. Since) s
-5 360 M
-( the replayed packet will not be using that expected sequence number) s
-5 349 M
-( \(the sequence number of the replayed packet will have already been) s
-5 338 M
-( passed by the receiver\) then the calculated MAC will not match the) s
-5 327 M
-( MAC received with the packet.) s
-5 305 M
-(9.2.4 Man-in-the-middle) s
-5 283 M
-( This protocol makes no assumptions nor provisions for an) s
-5 272 M
-( infrastructure or means for distributing the public keys of hosts. It) s
-5 261 M
-( is expected that this protocol will sometimes be used without first) s
-5 250 M
-( verifying the association between the server host key and the server) s
-5 239 M
-( host name. Such usage is vulnerable to man-in-the-middle attacks.) s
-5 228 M
-( This section describes this and encourages administrators and users) s
-5 217 M
-( to understand the importance of verifying this association before any) s
-5 206 M
-( session is initiated.) s
-5 184 M
-( There are three cases of man-in-the-middle attacks to consider. The) s
-5 173 M
-( first is where an attacker places a device between the client and the) s
-5 129 M
-(Ylonen & Moffat Expires March 31, 2004 [Page 17]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 18 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Protocol Architecture Oct 2003) s
-5 690 M
-( server before the session is initiated. In this case, the attack) s
-5 679 M
-( device is trying to mimic the legitimate server and will offer its) s
-5 668 M
-( public key to the client when the client initiates a session. If it) s
-5 657 M
-( were to offer the public key of the server, then it would not be able) s
-5 646 M
-( to decrypt or sign the transmissions between the legitimate server) s
-5 635 M
-( and the client unless it also had access to the private-key of the) s
-5 624 M
-( host. The attack device will also, simultaneously to this, initiate) s
-5 613 M
-( a session to the legitimate server masquerading itself as the client.) s
-5 602 M
-( If the public key of the server had been securely distributed to the) s
-5 591 M
-( client prior to that session initiation, the key offered to the) s
-5 580 M
-( client by the attack device will not match the key stored on the) s
-5 569 M
-( client. In that case, the user SHOULD be given a warning that the) s
-5 558 M
-( offered host key does not match the host key cached on the client.) s
-5 547 M
-( As described in Section 3.1 of [ARCH], the user may be free to accept) s
-5 536 M
-( the new key and continue the session. It is RECOMMENDED that the) s
-5 525 M
-( warning provide sufficient information to the user of the client) s
-5 514 M
-( device so they may make an informed decision. If the user chooses to) s
-5 503 M
-( continue the session with the stored public-key of the server \(not) s
-5 492 M
-( the public-key offered at the start of the session\), then the session) s
-5 481 M
-( specific data between the attacker and server will be different) s
-5 470 M
-( between the client-to-attacker session and the attacker-to-server) s
-5 459 M
-( sessions due to the randomness discussed above. From this, the) s
-5 448 M
-( attacker will not be able to make this attack work since the attacker) s
-5 437 M
-( will not be able to correctly sign packets containing this session) s
-5 426 M
-( specific data from the server since he does not have the private key) s
-5 415 M
-( of that server.) s
-5 393 M
-( The second case that should be considered is similar to the first) s
-5 382 M
-( case in that it also happens at the time of connection but this case) s
-5 371 M
-( points out the need for the secure distribution of server public) s
-5 360 M
-( keys. If the server public keys are not securely distributed then) s
-5 349 M
-( the client cannot know if it is talking to the intended server. An) s
-5 338 M
-( attacker may use social engineering techniques to pass off server) s
-5 327 M
-( keys to unsuspecting users and may then place a man-in-the-middle) s
-5 316 M
-( attack device between the legitimate server and the clients. If this) s
-5 305 M
-( is allowed to happen then the clients will form client-to-attacker) s
-5 294 M
-( sessions and the attacker will form attacker-to-server sessions and) s
-5 283 M
-( will be able to monitor and manipulate all of the traffic between the) s
-5 272 M
-( clients and the legitimate servers. Server administrators are) s
-5 261 M
-( encouraged to make host key fingerprints available for checking by) s
-5 250 M
-( some means whose security does not rely on the integrity of the) s
-5 239 M
-( actual host keys. Possible mechanisms are discussed in Section 3.1) s
-5 228 M
-( of [SSH-ARCH] and may also include secured Web pages, physical pieces) s
-5 217 M
-( of paper, etc. Implementors SHOULD provide recommendations on how) s
-5 206 M
-( best to do this with their implementation. Because the protocol is) s
-5 195 M
-( extensible, future extensions to the protocol may provide better) s
-5 184 M
-( mechanisms for dealing with the need to know the server's host key) s
-5 173 M
-( before connecting. For example, making the host key fingerprint) s
-5 129 M
-(Ylonen & Moffat Expires March 31, 2004 [Page 18]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (18,19) 10
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 19 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Protocol Architecture Oct 2003) s
-5 690 M
-( available through a secure DNS lookup, or using kerberos over gssapi) s
-5 679 M
-( during key exchange to authenticate the server are possibilities.) s
-5 657 M
-( In the third man-in-the-middle case, attackers may attempt to) s
-5 646 M
-( manipulate packets in transit between peers after the session has) s
-5 635 M
-( been established. As described in the Replay part of this section, a) s
-5 624 M
-( successful attack of this nature is very improbable. As in the) s
-5 613 M
-( Replay section, this reasoning does assume that the MAC is secure and) s
-5 602 M
-( that it is infeasible to construct inputs to a MAC algorithm to give) s
-5 591 M
-( a known output. This is discussed in much greater detail in Section) s
-5 580 M
-( 6 of RFC 2104. If the MAC algorithm has a vulnerability or is weak) s
-5 569 M
-( enough, then the attacker may be able to specify certain inputs to) s
-5 558 M
-( yield a known MAC. With that they may be able to alter the contents) s
-5 547 M
-( of a packet in transit. Alternatively the attacker may be able to) s
-5 536 M
-( exploit the algorithm vulnerability or weakness to find the shared) s
-5 525 M
-( secret by reviewing the MACs from captured packets. In either of) s
-5 514 M
-( those cases, an attacker could construct a packet or packets that) s
-5 503 M
-( could be inserted into an SSH stream. To prevent that, implementors) s
-5 492 M
-( are encouraged to utilize commonly accepted MAC algorithms and) s
-5 481 M
-( administrators are encouraged to watch current literature and) s
-5 470 M
-( discussions of cryptography to ensure that they are not using a MAC) s
-5 459 M
-( algorithm that has a recently found vulnerability or weakness.) s
-5 437 M
-( In summary, the use of this protocol without a reliable association) s
-5 426 M
-( of the binding between a host and its host keys is inherently) s
-5 415 M
-( insecure and is NOT RECOMMENDED. It may however be necessary in) s
-5 404 M
-( non-security critical environments, and will still provide protection) s
-5 393 M
-( against passive attacks. Implementors of protocols and applications) s
-5 382 M
-( running on top of this protocol should keep this possibility in mind.) s
-5 360 M
-(9.2.5 Denial-of-service) s
-5 338 M
-( This protocol is designed to be used over a reliable transport. If) s
-5 327 M
-( transmission errors or message manipulation occur, the connection is) s
-5 316 M
-( closed. The connection SHOULD be re-established if this occurs.) s
-5 305 M
-( Denial of service attacks of this type \("wire cutter"\) are almost) s
-5 294 M
-( impossible to avoid.) s
-5 272 M
-( In addition, this protocol is vulnerable to Denial of Service attacks) s
-5 261 M
-( because an attacker can force the server to go through the CPU and) s
-5 250 M
-( memory intensive tasks of connection setup and key exchange without) s
-5 239 M
-( authenticating. Implementors SHOULD provide features that make this) s
-5 228 M
-( more difficult. For example, only allowing connections from a subset) s
-5 217 M
-( of IPs known to have valid users.) s
-5 195 M
-(9.2.6 Covert Channels) s
-5 173 M
-( The protocol was not designed to eliminate covert channels. For) s
-5 129 M
-(Ylonen & Moffat Expires March 31, 2004 [Page 19]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 20 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Protocol Architecture Oct 2003) s
-5 690 M
-( example, the padding, SSH_MSG_IGNORE messages, and several other) s
-5 679 M
-( places in the protocol can be used to pass covert information, and) s
-5 668 M
-( the recipient has no reliable way to verify whether such information) s
-5 657 M
-( is being sent.) s
-5 635 M
-(9.2.7 Forward Secrecy) s
-5 613 M
-( It should be noted that the Diffie-Hellman key exchanges may provide) s
-5 602 M
-( perfect forward secrecy \(PFS\). PFS is essentially defined as the) s
-5 591 M
-( cryptographic property of a key-establishment protocol in which the) s
-5 580 M
-( compromise of a session key or long-term private key after a given) s
-5 569 M
-( session does not cause the compromise of any earlier session. [ANSI) s
-5 558 M
-( T1.523-2001] SSHv2 sessions resulting from a key exchange using) s
-5 547 M
-( diffie-hellman-group1-sha1 are secure even if private keying/) s
-5 536 M
-( authentication material is later revealed, but not if the session) s
-5 525 M
-( keys are revealed. So, given this definition of PFS, SSHv2 does have) s
-5 514 M
-( PFS. It is hoped that all other key exchange mechanisms proposed and) s
-5 503 M
-( used in the future will also provide PFS. This property is not) s
-5 492 M
-( commuted to any of the applications or protocols using SSH as a) s
-5 481 M
-( transport however. The transport layer of SSH provides) s
-5 470 M
-( confidentiality for password authentication and other methods that) s
-5 459 M
-( rely on secret data.) s
-5 437 M
-( Of course, if the DH private parameters for the client and server are) s
-5 426 M
-( revealed then the session key is revealed, but these items can be) s
-5 415 M
-( thrown away after the key exchange completes. It's worth pointing) s
-5 404 M
-( out that these items should not be allowed to end up on swap space) s
-5 393 M
-( and that they should be erased from memory as soon as the key) s
-5 382 M
-( exchange completes.) s
-5 360 M
-(9.3 Authentication Protocol) s
-5 338 M
-( The purpose of this protocol is to perform client user) s
-5 327 M
-( authentication. It assumes that this run over a secure transport) s
-5 316 M
-( layer protocol, which has already authenticated the server machine,) s
-5 305 M
-( established an encrypted communications channel, and computed a) s
-5 294 M
-( unique session identifier for this session.) s
-5 272 M
-( Several authentication methods with different security) s
-5 261 M
-( characteristics are allowed. It is up to the server's local policy) s
-5 250 M
-( to decide which methods \(or combinations of methods\) it is willing to) s
-5 239 M
-( accept for each user. Authentication is no stronger than the weakest) s
-5 228 M
-( combination allowed.) s
-5 206 M
-( The server may go into a "sleep" period after repeated unsuccessful) s
-5 195 M
-( authentication attempts to make key search more difficult for) s
-5 184 M
-( attackers. Care should be taken so that this doesn't become a) s
-5 173 M
-( self-denial of service vector.) s
-5 129 M
-(Ylonen & Moffat Expires March 31, 2004 [Page 20]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (20,21) 11
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 21 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Protocol Architecture Oct 2003) s
-5 690 M
-(9.3.1 Weak Transport) s
-5 668 M
-( If the transport layer does not provide confidentiality,) s
-5 657 M
-( authentication methods that rely on secret data SHOULD be disabled.) s
-5 646 M
-( If it does not provide strong integrity protection, requests to) s
-5 635 M
-( change authentication data \(e.g. a password change\) SHOULD be) s
-5 624 M
-( disabled to prevent an attacker from modifying the ciphertext) s
-5 613 M
-( without being noticed, or rendering the new authentication data) s
-5 602 M
-( unusable \(denial of service\).) s
-5 580 M
-( The assumption as stated above that the Authentication Protocol only) s
-5 569 M
-( run over a secure transport that has previously authenticated the) s
-5 558 M
-( server is very important to note. People deploying SSH are reminded) s
-5 547 M
-( of the consequences of man-in-the-middle attacks if the client does) s
-5 536 M
-( not have a very strong a priori association of the server with the) s
-5 525 M
-( host key of that server. Specifically for the case of the) s
-5 514 M
-( Authentication Protocol the client may form a session to a) s
-5 503 M
-( man-in-the-middle attack device and divulge user credentials such as) s
-5 492 M
-( their username and password. Even in the cases of authentication) s
-5 481 M
-( where no user credentials are divulged, an attacker may still gain) s
-5 470 M
-( information they shouldn't have by capturing key-strokes in much the) s
-5 459 M
-( same way that a honeypot works.) s
-5 437 M
-(9.3.2 Debug messages) s
-5 415 M
-( Special care should be taken when designing debug messages. These) s
-5 404 M
-( messages may reveal surprising amounts of information about the host) s
-5 393 M
-( if not properly designed. Debug messages can be disabled \(during) s
-5 382 M
-( user authentication phase\) if high security is required.) s
-5 371 M
-( Administrators of host machines should make all attempts to) s
-5 360 M
-( compartmentalize all event notification messages and protect them) s
-5 349 M
-( from unwarranted observation. Developers should be aware of the) s
-5 338 M
-( sensitive nature of some of the normal event messages and debug) s
-5 327 M
-( messages and may want to provide guidance to administrators on ways) s
-5 316 M
-( to keep this information away from unauthorized people. Developers) s
-5 305 M
-( should consider minimizing the amount of sensitive information) s
-5 294 M
-( obtainable by users during the authentication phase in accordance) s
-5 283 M
-( with the local policies. For this reason, it is RECOMMENDED that) s
-5 272 M
-( debug messages be initially disabled at the time of deployment and) s
-5 261 M
-( require an active decision by an administrator to allow them to be) s
-5 250 M
-( enabled. It is also RECOMMENDED that a message expressing this) s
-5 239 M
-( concern be presented to the administrator of a system when the action) s
-5 228 M
-( is taken to enable debugging messages.) s
-5 206 M
-(9.3.3 Local security policy) s
-5 184 M
-( Implementer MUST ensure that the credentials provided validate the) s
-5 173 M
-( professed user and also MUST ensure that the local policy of the) s
-5 129 M
-(Ylonen & Moffat Expires March 31, 2004 [Page 21]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 22 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Protocol Architecture Oct 2003) s
-5 690 M
-( server permits the user the access requested. In particular, because) s
-5 679 M
-( of the flexible nature of the SSH connection protocol, it may not be) s
-5 668 M
-( possible to determine the local security policy, if any, that should) s
-5 657 M
-( apply at the time of authentication because the kind of service being) s
-5 646 M
-( requested is not clear at that instant. For example, local policy) s
-5 635 M
-( might allow a user to access files on the server, but not start an) s
-5 624 M
-( interactive shell. However, during the authentication protocol, it is) s
-5 613 M
-( not known whether the user will be accessing files or attempting to) s
-5 602 M
-( use an interactive shell, or even both. In any event, where local) s
-5 591 M
-( security policy for the server host exists, it MUST be applied and) s
-5 580 M
-( enforced correctly.) s
-5 558 M
-( Implementors are encouraged to provide a default local policy and) s
-5 547 M
-( make its parameters known to administrators and users. At the) s
-5 536 M
-( discretion of the implementors, this default policy may be along the) s
-5 525 M
-( lines of 'anything goes' where there are no restrictions placed upon) s
-5 514 M
-( users, or it may be along the lines of 'excessively restrictive' in) s
-5 503 M
-( which case the administrators will have to actively make changes to) s
-5 492 M
-( this policy to meet their needs. Alternatively, it may be some) s
-5 481 M
-( attempt at providing something practical and immediately useful to) s
-5 470 M
-( the administrators of the system so they don't have to put in much) s
-5 459 M
-( effort to get SSH working. Whatever choice is made MUST be applied) s
-5 448 M
-( and enforced as required above.) s
-5 426 M
-(9.3.4 Public key authentication) s
-5 404 M
-( The use of public-key authentication assumes that the client host has) s
-5 393 M
-( not been compromised. It also assumes that the private-key of the) s
-5 382 M
-( server host has not been compromised.) s
-5 360 M
-( This risk can be mitigated by the use of passphrases on private keys;) s
-5 349 M
-( however, this is not an enforceable policy. The use of smartcards,) s
-5 338 M
-( or other technology to make passphrases an enforceable policy is) s
-5 327 M
-( suggested.) s
-5 305 M
-( The server could require both password and public-key authentication,) s
-5 294 M
-( however, this requires the client to expose its password to the) s
-5 283 M
-( server \(see section on password authentication below.\)) s
-5 261 M
-(9.3.5 Password authentication) s
-5 239 M
-( The password mechanism as specified in the authentication protocol) s
-5 228 M
-( assumes that the server has not been compromised. If the server has) s
-5 217 M
-( been compromised, using password authentication will reveal a valid) s
-5 206 M
-( username / password combination to the attacker, which may lead to) s
-5 195 M
-( further compromises.) s
-5 173 M
-( This vulnerability can be mitigated by using an alternative form of) s
-5 129 M
-(Ylonen & Moffat Expires March 31, 2004 [Page 22]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (22,23) 12
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 23 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Protocol Architecture Oct 2003) s
-5 690 M
-( authentication. For example, public-key authentication makes no) s
-5 679 M
-( assumptions about security on the server.) s
-5 657 M
-(9.3.6 Host based authentication) s
-5 635 M
-( Host based authentication assumes that the client has not been) s
-5 624 M
-( compromised. There are no mitigating strategies, other than to use) s
-5 613 M
-( host based authentication in combination with another authentication) s
-5 602 M
-( method.) s
-5 580 M
-(9.4 Connection protocol) s
-5 558 M
-(9.4.1 End point security) s
-5 536 M
-( End point security is assumed by the connection protocol. If the) s
-5 525 M
-( server has been compromised, any terminal sessions, port forwarding,) s
-5 514 M
-( or systems accessed on the host are compromised. There are no) s
-5 503 M
-( mitigating factors for this.) s
-5 481 M
-( If the client end point has been compromised, and the server fails to) s
-5 470 M
-( stop the attacker at the authentication protocol, all services) s
-5 459 M
-( exposed \(either as subsystems or through forwarding\) will be) s
-5 448 M
-( vulnerable to attack. Implementors SHOULD provide mechanisms for) s
-5 437 M
-( administrators to control which services are exposed to limit the) s
-5 426 M
-( vulnerability of other services.) s
-5 404 M
-( These controls might include controlling which machines and ports can) s
-5 393 M
-( be target in 'port-forwarding' operations, which users are allowed to) s
-5 382 M
-( use interactive shell facilities, or which users are allowed to use) s
-5 371 M
-( exposed subsystems.) s
-5 349 M
-(9.4.2 Proxy forwarding) s
-5 327 M
-( The SSH connection protocol allows for proxy forwarding of other) s
-5 316 M
-( protocols such as SNMP, POP3, and HTTP. This may be a concern for) s
-5 305 M
-( network administrators who wish to control the access of certain) s
-5 294 M
-( applications by users located outside of their physical location.) s
-5 283 M
-( Essentially, the forwarding of these protocols may violate site) s
-5 272 M
-( specific security policies as they may be undetectably tunneled) s
-5 261 M
-( through a firewall. Implementors SHOULD provide an administrative) s
-5 250 M
-( mechanism to control the proxy forwarding functionality so that site) s
-5 239 M
-( specific security policies may be upheld.) s
-5 217 M
-( In addition, a reverse proxy forwarding functionality is available,) s
-5 206 M
-( which again can be used to bypass firewall controls.) s
-5 184 M
-( As indicated above, end-point security is assumed during proxy) s
-5 173 M
-( forwarding operations. Failure of end-point security will compromise) s
-5 129 M
-(Ylonen & Moffat Expires March 31, 2004 [Page 23]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 24 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Protocol Architecture Oct 2003) s
-5 690 M
-( all data passed over proxy forwarding.) s
-5 668 M
-(9.4.3 X11 forwarding) s
-5 646 M
-( Another form of proxy forwarding provided by the ssh connection) s
-5 635 M
-( protocol is the forwarding of the X11 protocol. If end-point) s
-5 624 M
-( security has been compromised, X11 forwarding may allow attacks) s
-5 613 M
-( against the X11 server. Users and administrators should, as a matter) s
-5 602 M
-( of course, use appropriate X11 security mechanisms to prevent) s
-5 591 M
-( unauthorized use of the X11 server. Implementors, administrators and) s
-5 580 M
-( users who wish to further explore the security mechanisms of X11 are) s
-5 569 M
-( invited to read [SCHEIFLER] and analyze previously reported problems) s
-5 558 M
-( with the interactions between SSH forwarding and X11 in CERT) s
-5 547 M
-( vulnerabilities VU#363181 and VU#118892 [CERT].) s
-5 525 M
-( X11 display forwarding with SSH, by itself, is not sufficient to) s
-5 514 M
-( correct well known problems with X11 security [VENEMA]. However, X11) s
-5 503 M
-( display forwarding in SSHv2 \(or other, secure protocols\), combined) s
-5 492 M
-( with actual and pseudo-displays which accept connections only over) s
-5 481 M
-( local IPC mechanisms authorized by permissions or ACLs, does correct) s
-5 470 M
-( many X11 security problems as long as the "none" MAC is not used. It) s
-5 459 M
-( is RECOMMENDED that X11 display implementations default to allowing) s
-5 448 M
-( display opens only over local IPC. It is RECOMMENDED that SSHv2) s
-5 437 M
-( server implementations that support X11 forwarding default to) s
-5 426 M
-( allowing display opens only over local IPC. On single-user systems) s
-5 415 M
-( it might be reasonable to default to allowing local display opens) s
-5 404 M
-( over TCP/IP.) s
-5 382 M
-( Implementors of the X11 forwarding protocol SHOULD implement the) s
-5 371 M
-( magic cookie access checking spoofing mechanism as described in) s
-5 360 M
-( [ssh-connect] as an additional mechanism to prevent unauthorized use) s
-5 349 M
-( of the proxy.) s
-5 327 M
-(Normative References) s
-5 305 M
-( [SSH-ARCH]) s
-5 294 M
-( Ylonen, T., "SSH Protocol Architecture", I-D) s
-5 283 M
-( draft-ietf-architecture-15.txt, Oct 2003.) s
-5 261 M
-( [SSH-TRANS]) s
-5 250 M
-( Ylonen, T., "SSH Transport Layer Protocol", I-D) s
-5 239 M
-( draft-ietf-transport-17.txt, Oct 2003.) s
-5 217 M
-( [SSH-USERAUTH]) s
-5 206 M
-( Ylonen, T., "SSH Authentication Protocol", I-D) s
-5 195 M
-( draft-ietf-userauth-18.txt, Oct 2003.) s
-5 173 M
-( [SSH-CONNECT]) s
-5 129 M
-(Ylonen & Moffat Expires March 31, 2004 [Page 24]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (24,25) 13
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 25 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Protocol Architecture Oct 2003) s
-5 690 M
-( Ylonen, T., "SSH Connection Protocol", I-D) s
-5 679 M
-( draft-ietf-connect-18.txt, Oct 2003.) s
-5 657 M
-( [SSH-NUMBERS]) s
-5 646 M
-( Lehtinen, S. and D. Moffat, "SSH Protocol Assigned) s
-5 635 M
-( Numbers", I-D draft-ietf-secsh-assignednumbers-05.txt, Oct) s
-5 624 M
-( 2003.) s
-5 602 M
-( [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate) s
-5 591 M
-( Requirement Levels", BCP 14, RFC 2119, March 1997.) s
-5 569 M
-(Informative References) s
-5 547 M
-( [FIPS-186]) s
-5 536 M
-( Federal Information Processing Standards Publication,) s
-5 525 M
-( "FIPS PUB 186, Digital Signature Standard", May 1994.) s
-5 503 M
-( [FIPS-197]) s
-5 492 M
-( National Institue of Standards and Technology, "FIPS 197,) s
-5 481 M
-( Specification for the Advanced Encryption Standard",) s
-5 470 M
-( November 2001.) s
-5 448 M
-( [ANSI T1.523-2001]) s
-5 437 M
-( American National Standards Insitute, Inc., "Telecom) s
-5 426 M
-( Glossary 2000", February 2001.) s
-5 404 M
-( [SCHEIFLER]) s
-5 393 M
-( Scheifler, R., "X Window System : The Complete Reference) s
-5 382 M
-( to Xlib, X Protocol, Icccm, Xlfd, 3rd edition.", Digital) s
-5 371 M
-( Press ISBN 1555580882, Feburary 1992.) s
-5 349 M
-( [RFC0854] Postel, J. and J. Reynolds, "Telnet Protocol) s
-5 338 M
-( Specification", STD 8, RFC 854, May 1983.) s
-5 316 M
-( [RFC0894] Hornig, C., "Standard for the transmission of IP datagrams) s
-5 305 M
-( over Ethernet networks", STD 41, RFC 894, April 1984.) s
-5 283 M
-( [RFC1034] Mockapetris, P., "Domain names - concepts and facilities",) s
-5 272 M
-( STD 13, RFC 1034, November 1987.) s
-5 250 M
-( [RFC1134] Perkins, D., "Point-to-Point Protocol: A proposal for) s
-5 239 M
-( multi-protocol transmission of datagrams over) s
-5 228 M
-( Point-to-Point links", RFC 1134, November 1989.) s
-5 206 M
-( [RFC1282] Kantor, B., "BSD Rlogin", RFC 1282, December 1991.) s
-5 184 M
-( [RFC1510] Kohl, J. and B. Neuman, "The Kerberos Network) s
-5 173 M
-( Authentication Service \(V5\)", RFC 1510, September 1993.) s
-5 129 M
-(Ylonen & Moffat Expires March 31, 2004 [Page 25]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 26 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Protocol Architecture Oct 2003) s
-5 690 M
-( [RFC1700] Reynolds, J. and J. Postel, "Assigned Numbers", RFC 1700,) s
-5 679 M
-( October 1994.) s
-5 657 M
-( [RFC1750] Eastlake, D., Crocker, S. and J. Schiller, "Randomness) s
-5 646 M
-( Recommendations for Security", RFC 1750, December 1994.) s
-5 624 M
-( [RFC3066] Alvestrand, H., "Tags for the Identification of) s
-5 613 M
-( Languages", BCP 47, RFC 3066, January 2001.) s
-5 591 M
-( [RFC1964] Linn, J., "The Kerberos Version 5 GSS-API Mechanism", RFC) s
-5 580 M
-( 1964, June 1996.) s
-5 558 M
-( [RFC2025] Adams, C., "The Simple Public-Key GSS-API Mechanism) s
-5 547 M
-( \(SPKM\)", RFC 2025, October 1996.) s
-5 525 M
-( [RFC2085] Oehler, M. and R. Glenn, "HMAC-MD5 IP Authentication with) s
-5 514 M
-( Replay Prevention", RFC 2085, February 1997.) s
-5 492 M
-( [RFC2104] Krawczyk, H., Bellare, M. and R. Canetti, "HMAC:) s
-5 481 M
-( Keyed-Hashing for Message Authentication", RFC 2104,) s
-5 470 M
-( February 1997.) s
-5 448 M
-( [RFC2246] Dierks, T., Allen, C., Treese, W., Karlton, P., Freier, A.) s
-5 437 M
-( and P. Kocher, "The TLS Protocol Version 1.0", RFC 2246,) s
-5 426 M
-( January 1999.) s
-5 404 M
-( [RFC2279] Yergeau, F., "UTF-8, a transformation format of ISO) s
-5 393 M
-( 10646", RFC 2279, January 1998.) s
-5 371 M
-( [RFC2410] Glenn, R. and S. Kent, "The NULL Encryption Algorithm and) s
-5 360 M
-( Its Use With IPsec", RFC 2410, November 1998.) s
-5 338 M
-( [RFC2434] Narten, T. and H. Alvestrand, "Guidelines for Writing an) s
-5 327 M
-( IANA Considerations Section in RFCs", BCP 26, RFC 2434,) s
-5 316 M
-( October 1998.) s
-5 294 M
-( [RFC2743] Linn, J., "Generic Security Service Application Program) s
-5 283 M
-( Interface Version 2, Update 1", RFC 2743, January 2000.) s
-5 261 M
-( [SCHNEIER]) s
-5 250 M
-( Schneier, B., "Applied Cryptography Second Edition:) s
-5 239 M
-( protocols algorithms and source in code in C", 1996.) s
-5 217 M
-( [KAUFMAN,PERLMAN,SPECINER]) s
-5 206 M
-( Kaufman, C., Perlman, R. and M. Speciner, "Network) s
-5 195 M
-( Security: PRIVATE Communication in a PUBLIC World", 1995.) s
-5 173 M
-( [CERT] CERT Coordination Center, The., "http://www.cert.org/nav/) s
-5 129 M
-(Ylonen & Moffat Expires March 31, 2004 [Page 26]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (26,27) 14
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 27 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Protocol Architecture Oct 2003) s
-5 690 M
-( index_red.html".) s
-5 668 M
-( [VENEMA] Venema, W., "Murphy's Law and Computer Security",) s
-5 657 M
-( Proceedings of 6th USENIX Security Symposium, San Jose CA) s
-5 646 M
-( http://www.usenix.org/publications/library/proceedings/) s
-5 635 M
-( sec96/venema.html, July 1996.) s
-5 613 M
-( [ROGAWAY] Rogaway, P., "Problems with Proposed IP Cryptography",) s
-5 602 M
-( Unpublished paper http://www.cs.ucdavis.edu/~rogaway/) s
-5 591 M
-( papers/draft-rogaway-ipsec-comments-00.txt, 1996.) s
-5 569 M
-( [DAI] Dai, W., "An attack against SSH2 protocol", Email to the) s
-5 558 M
-( SECSH Working Group [email protected] ftp://) s
-5 547 M
-( ftp.ietf.org/ietf-mail-archive/secsh/2002-02.mail, Feb) s
-5 536 M
-( 2002.) s
-5 514 M
-( [BELLARE,KOHNO,NAMPREMPRE]) s
-5 503 M
-( Bellaire, M., Kohno, T. and C. Namprempre, "Authenticated) s
-5 492 M
-( Encryption in SSH: Fixing the SSH Binary Packet Protocol",) s
-5 481 M
-( , Sept 2002.) s
-5 448 M
-(Authors' Addresses) s
-5 426 M
-( Tatu Ylonen) s
-5 415 M
-( SSH Communications Security Corp) s
-5 404 M
-( Fredrikinkatu 42) s
-5 393 M
-( HELSINKI FIN-00100) s
-5 382 M
-( Finland) s
-5 360 M
-( EMail: [email protected]) s
-5 327 M
-( Darren J. Moffat \(editor\)) s
-5 316 M
-( Sun Microsystems, Inc) s
-5 305 M
-( 17 Network Circle) s
-5 294 M
-( Menlo Park CA 94025) s
-5 283 M
-( USA) s
-5 261 M
-( EMail: [email protected]) s
-5 129 M
-(Ylonen & Moffat Expires March 31, 2004 [Page 27]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 28 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Protocol Architecture Oct 2003) s
-5 690 M
-(Intellectual Property Statement) s
-5 668 M
-( The IETF takes no position regarding the validity or scope of any) s
-5 657 M
-( intellectual property or other rights that might be claimed to) s
-5 646 M
-( pertain to the implementation or use of the technology described in) s
-5 635 M
-( this document or the extent to which any license under such rights) s
-5 624 M
-( might or might not be available; neither does it represent that it) s
-5 613 M
-( has made any effort to identify any such rights. Information on the) s
-5 602 M
-( IETF's procedures with respect to rights in standards-track and) s
-5 591 M
-( standards-related documentation can be found in BCP-11. Copies of) s
-5 580 M
-( claims of rights made available for publication and any assurances of) s
-5 569 M
-( licenses to be made available, or the result of an attempt made to) s
-5 558 M
-( obtain a general license or permission for the use of such) s
-5 547 M
-( proprietary rights by implementors or users of this specification can) s
-5 536 M
-( be obtained from the IETF Secretariat.) s
-5 514 M
-( The IETF invites any interested party to bring to its attention any) s
-5 503 M
-( copyrights, patents or patent applications, or other proprietary) s
-5 492 M
-( rights which may cover technology that may be required to practice) s
-5 481 M
-( this standard. Please address the information to the IETF Executive) s
-5 470 M
-( Director.) s
-5 448 M
-( The IETF has been notified of intellectual property rights claimed in) s
-5 437 M
-( regard to some or all of the specification contained in this) s
-5 426 M
-( document. For more information consult the online list of claimed) s
-5 415 M
-( rights.) s
-5 382 M
-(Full Copyright Statement) s
-5 360 M
-( Copyright \(C\) The Internet Society \(2003\). All Rights Reserved.) s
-5 338 M
-( This document and translations of it may be copied and furnished to) s
-5 327 M
-( others, and derivative works that comment on or otherwise explain it) s
-5 316 M
-( or assist in its implementation may be prepared, copied, published) s
-5 305 M
-( and distributed, in whole or in part, without restriction of any) s
-5 294 M
-( kind, provided that the above copyright notice and this paragraph are) s
-5 283 M
-( included on all such copies and derivative works. However, this) s
-5 272 M
-( document itself may not be modified in any way, such as by removing) s
-5 261 M
-( the copyright notice or references to the Internet Society or other) s
-5 250 M
-( Internet organizations, except as needed for the purpose of) s
-5 239 M
-( developing Internet standards in which case the procedures for) s
-5 228 M
-( copyrights defined in the Internet Standards process must be) s
-5 217 M
-( followed, or as required to translate it into languages other than) s
-5 206 M
-( English.) s
-5 184 M
-( The limited permissions granted above are perpetual and will not be) s
-5 173 M
-( revoked by the Internet Society or its successors or assignees.) s
-5 129 M
-(Ylonen & Moffat Expires March 31, 2004 [Page 28]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (28,29) 15
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 29 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Protocol Architecture Oct 2003) s
-5 690 M
-( This document and the information contained herein is provided on an) s
-5 679 M
-( "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING) s
-5 668 M
-( TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING) s
-5 657 M
-( BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION) s
-5 646 M
-( HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF) s
-5 635 M
-( MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.) s
-5 602 M
-(Acknowledgment) s
-5 580 M
-( Funding for the RFC Editor function is currently provided by the) s
-5 569 M
-( Internet Society.) s
-5 129 M
-(Ylonen & Moffat Expires March 31, 2004 [Page 29]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-showpage
-PStoPSsaved restore
-%%Trailer
-%%Pages: 29
-%%DocumentNeededResources: font Courier-Bold Courier
-%%EOF
diff --git a/lib/ssh/doc/standard/draft-ietf-secsh-architecture-15.txt b/lib/ssh/doc/standard/draft-ietf-secsh-architecture-15.txt
deleted file mode 100644
index 18070e8485..0000000000
--- a/lib/ssh/doc/standard/draft-ietf-secsh-architecture-15.txt
+++ /dev/null
@@ -1,1624 +0,0 @@
-
-
-
-Network Working Group T. Ylonen
-Internet-Draft SSH Communications Security Corp
-Expires: March 31, 2004 D. Moffat, Ed.
- Sun Microsystems, Inc
- Oct 2003
-
-
- SSH Protocol Architecture
- draft-ietf-secsh-architecture-15.txt
-
-Status of this Memo
-
- This document is an Internet-Draft and is in full conformance with
- all provisions of Section 10 of RFC2026.
-
- Internet-Drafts are working documents of the Internet Engineering
- Task Force (IETF), its areas, and its working groups. Note that other
- groups may also distribute working documents as Internet-Drafts.
-
- Internet-Drafts are draft documents valid for a maximum of six months
- and may be updated, replaced, or obsoleted by other documents at any
- time. It is inappropriate to use Internet-Drafts as reference
- material or to cite them other than as "work in progress."
-
- The list of current Internet-Drafts can be accessed at http://
- www.ietf.org/ietf/1id-abstracts.txt.
-
- The list of Internet-Draft Shadow Directories can be accessed at
- http://www.ietf.org/shadow.html.
-
- This Internet-Draft will expire on March 31, 2004.
-
-Copyright Notice
-
- Copyright (C) The Internet Society (2003). All Rights Reserved.
-
-Abstract
-
- SSH is a protocol for secure remote login and other secure network
- services over an insecure network. This document describes the
- architecture of the SSH protocol, as well as the notation and
- terminology used in SSH protocol documents. It also discusses the SSH
- algorithm naming system that allows local extensions. The SSH
- protocol consists of three major components: The Transport Layer
- Protocol provides server authentication, confidentiality, and
- integrity with perfect forward secrecy. The User Authentication
- Protocol authenticates the client to the server. The Connection
- Protocol multiplexes the encrypted tunnel into several logical
- channels. Details of these protocols are described in separate
-
-
-
-Ylonen & Moffat Expires March 31, 2004 [Page 1]
-
-Internet-Draft SSH Protocol Architecture Oct 2003
-
-
- documents.
-
-Table of Contents
-
- 1. Contributors . . . . . . . . . . . . . . . . . . . . . . . . 3
- 2. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3
- 3. Specification of Requirements . . . . . . . . . . . . . . . 3
- 4. Architecture . . . . . . . . . . . . . . . . . . . . . . . . 3
- 4.1 Host Keys . . . . . . . . . . . . . . . . . . . . . . . . . 4
- 4.2 Extensibility . . . . . . . . . . . . . . . . . . . . . . . 5
- 4.3 Policy Issues . . . . . . . . . . . . . . . . . . . . . . . 5
- 4.4 Security Properties . . . . . . . . . . . . . . . . . . . . 6
- 4.5 Packet Size and Overhead . . . . . . . . . . . . . . . . . . 6
- 4.6 Localization and Character Set Support . . . . . . . . . . . 7
- 5. Data Type Representations Used in the SSH Protocols . . . . 8
- 6. Algorithm Naming . . . . . . . . . . . . . . . . . . . . . . 10
- 7. Message Numbers . . . . . . . . . . . . . . . . . . . . . . 11
- 8. IANA Considerations . . . . . . . . . . . . . . . . . . . . 11
- 9. Security Considerations . . . . . . . . . . . . . . . . . . 12
- 9.1 Pseudo-Random Number Generation . . . . . . . . . . . . . . 12
- 9.2 Transport . . . . . . . . . . . . . . . . . . . . . . . . . 13
- 9.2.1 Confidentiality . . . . . . . . . . . . . . . . . . . . . . 13
- 9.2.2 Data Integrity . . . . . . . . . . . . . . . . . . . . . . . 16
- 9.2.3 Replay . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
- 9.2.4 Man-in-the-middle . . . . . . . . . . . . . . . . . . . . . 17
- 9.2.5 Denial-of-service . . . . . . . . . . . . . . . . . . . . . 19
- 9.2.6 Covert Channels . . . . . . . . . . . . . . . . . . . . . . 19
- 9.2.7 Forward Secrecy . . . . . . . . . . . . . . . . . . . . . . 20
- 9.3 Authentication Protocol . . . . . . . . . . . . . . . . . . 20
- 9.3.1 Weak Transport . . . . . . . . . . . . . . . . . . . . . . . 21
- 9.3.2 Debug messages . . . . . . . . . . . . . . . . . . . . . . . 21
- 9.3.3 Local security policy . . . . . . . . . . . . . . . . . . . 21
- 9.3.4 Public key authentication . . . . . . . . . . . . . . . . . 22
- 9.3.5 Password authentication . . . . . . . . . . . . . . . . . . 22
- 9.3.6 Host based authentication . . . . . . . . . . . . . . . . . 23
- 9.4 Connection protocol . . . . . . . . . . . . . . . . . . . . 23
- 9.4.1 End point security . . . . . . . . . . . . . . . . . . . . . 23
- 9.4.2 Proxy forwarding . . . . . . . . . . . . . . . . . . . . . . 23
- 9.4.3 X11 forwarding . . . . . . . . . . . . . . . . . . . . . . . 24
- Normative References . . . . . . . . . . . . . . . . . . . . 24
- Informative References . . . . . . . . . . . . . . . . . . . 25
- Authors' Addresses . . . . . . . . . . . . . . . . . . . . . 27
- Intellectual Property and Copyright Statements . . . . . . . 28
-
-
-
-
-
-
-
-
-Ylonen & Moffat Expires March 31, 2004 [Page 2]
-
-Internet-Draft SSH Protocol Architecture Oct 2003
-
-
-1. Contributors
-
- The major original contributors of this document were: Tatu Ylonen,
- Tero Kivinen, Timo J. Rinne, Sami Lehtinen (all of SSH Communications
- Security Corp), and Markku-Juhani O. Saarinen (University of
- Jyvaskyla)
-
- The document editor is: [email protected]. Comments on this
- internet draft should be sent to the IETF SECSH working group,
- details at: http://ietf.org/html.charters/secsh-charter.html
-
-2. Introduction
-
- SSH is a protocol for secure remote login and other secure network
- services over an insecure network. It consists of three major
- components:
- o The Transport Layer Protocol [SSH-TRANS] provides server
- authentication, confidentiality, and integrity. It may optionally
- also provide compression. The transport layer will typically be
- run over a TCP/IP connection, but might also be used on top of any
- other reliable data stream.
- o The User Authentication Protocol [SSH-USERAUTH] authenticates the
- client-side user to the server. It runs over the transport layer
- protocol.
- o The Connection Protocol [SSH-CONNECT] multiplexes the encrypted
- tunnel into several logical channels. It runs over the user
- authentication protocol.
-
- The client sends a service request once a secure transport layer
- connection has been established. A second service request is sent
- after user authentication is complete. This allows new protocols to
- be defined and coexist with the protocols listed above.
-
- The connection protocol provides channels that can be used for a wide
- range of purposes. Standard methods are provided for setting up
- secure interactive shell sessions and for forwarding ("tunneling")
- arbitrary TCP/IP ports and X11 connections.
-
-3. Specification of Requirements
-
- All documents related to the SSH protocols shall use the keywords
- "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD",
- "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" to describe
- requirements. They are to be interpreted as described in [RFC2119].
-
-4. Architecture
-
-
-
-
-
-Ylonen & Moffat Expires March 31, 2004 [Page 3]
-
-Internet-Draft SSH Protocol Architecture Oct 2003
-
-
-4.1 Host Keys
-
- Each server host SHOULD have a host key. Hosts MAY have multiple
- host keys using multiple different algorithms. Multiple hosts MAY
- share the same host key. If a host has keys at all, it MUST have at
- least one key using each REQUIRED public key algorithm (DSS
- [FIPS-186]).
-
- The server host key is used during key exchange to verify that the
- client is really talking to the correct server. For this to be
- possible, the client must have a priori knowledge of the server's
- public host key.
-
- Two different trust models can be used:
- o The client has a local database that associates each host name (as
- typed by the user) with the corresponding public host key. This
- method requires no centrally administered infrastructure, and no
- third-party coordination. The downside is that the database of
- name-to-key associations may become burdensome to maintain.
- o The host name-to-key association is certified by some trusted
- certification authority. The client only knows the CA root key,
- and can verify the validity of all host keys certified by accepted
- CAs.
-
- The second alternative eases the maintenance problem, since
- ideally only a single CA key needs to be securely stored on the
- client. On the other hand, each host key must be appropriately
- certified by a central authority before authorization is possible.
- Also, a lot of trust is placed on the central infrastructure.
-
- The protocol provides the option that the server name - host key
- association is not checked when connecting to the host for the first
- time. This allows communication without prior communication of host
- keys or certification. The connection still provides protection
- against passive listening; however, it becomes vulnerable to active
- man-in-the-middle attacks. Implementations SHOULD NOT normally allow
- such connections by default, as they pose a potential security
- problem. However, as there is no widely deployed key infrastructure
- available on the Internet yet, this option makes the protocol much
- more usable during the transition time until such an infrastructure
- emerges, while still providing a much higher level of security than
- that offered by older solutions (e.g. telnet [RFC-854] and rlogin
- [RFC-1282]).
-
- Implementations SHOULD try to make the best effort to check host
- keys. An example of a possible strategy is to only accept a host key
- without checking the first time a host is connected, save the key in
- a local database, and compare against that key on all future
-
-
-
-Ylonen & Moffat Expires March 31, 2004 [Page 4]
-
-Internet-Draft SSH Protocol Architecture Oct 2003
-
-
- connections to that host.
-
- Implementations MAY provide additional methods for verifying the
- correctness of host keys, e.g. a hexadecimal fingerprint derived from
- the SHA-1 hash of the public key. Such fingerprints can easily be
- verified by using telephone or other external communication channels.
-
- All implementations SHOULD provide an option to not accept host keys
- that cannot be verified.
-
- We believe that ease of use is critical to end-user acceptance of
- security solutions, and no improvement in security is gained if the
- new solutions are not used. Thus, providing the option not to check
- the server host key is believed to improve the overall security of
- the Internet, even though it reduces the security of the protocol in
- configurations where it is allowed.
-
-4.2 Extensibility
-
- We believe that the protocol will evolve over time, and some
- organizations will want to use their own encryption, authentication
- and/or key exchange methods. Central registration of all extensions
- is cumbersome, especially for experimental or classified features.
- On the other hand, having no central registration leads to conflicts
- in method identifiers, making interoperability difficult.
-
- We have chosen to identify algorithms, methods, formats, and
- extension protocols with textual names that are of a specific format.
- DNS names are used to create local namespaces where experimental or
- classified extensions can be defined without fear of conflicts with
- other implementations.
-
- One design goal has been to keep the base protocol as simple as
- possible, and to require as few algorithms as possible. However, all
- implementations MUST support a minimal set of algorithms to ensure
- interoperability (this does not imply that the local policy on all
- hosts would necessary allow these algorithms). The mandatory
- algorithms are specified in the relevant protocol documents.
-
- Additional algorithms, methods, formats, and extension protocols can
- be defined in separate drafts. See Section Algorithm Naming (Section
- 6) for more information.
-
-4.3 Policy Issues
-
- The protocol allows full negotiation of encryption, integrity, key
- exchange, compression, and public key algorithms and formats.
- Encryption, integrity, public key, and compression algorithms can be
-
-
-
-Ylonen & Moffat Expires March 31, 2004 [Page 5]
-
-Internet-Draft SSH Protocol Architecture Oct 2003
-
-
- different for each direction.
-
- The following policy issues SHOULD be addressed in the configuration
- mechanisms of each implementation:
- o Encryption, integrity, and compression algorithms, separately for
- each direction. The policy MUST specify which is the preferred
- algorithm (e.g. the first algorithm listed in each category).
- o Public key algorithms and key exchange method to be used for host
- authentication. The existence of trusted host keys for different
- public key algorithms also affects this choice.
- o The authentication methods that are to be required by the server
- for each user. The server's policy MAY require multiple
- authentication for some or all users. The required algorithms MAY
- depend on the location where the user is trying to log in from.
- o The operations that the user is allowed to perform using the
- connection protocol. Some issues are related to security; for
- example, the policy SHOULD NOT allow the server to start sessions
- or run commands on the client machine, and MUST NOT allow
- connections to the authentication agent unless forwarding such
- connections has been requested. Other issues, such as which TCP/
- IP ports can be forwarded and by whom, are clearly issues of local
- policy. Many of these issues may involve traversing or bypassing
- firewalls, and are interrelated with the local security policy.
-
-4.4 Security Properties
-
- The primary goal of the SSH protocol is improved security on the
- Internet. It attempts to do this in a way that is easy to deploy,
- even at the cost of absolute security.
- o All encryption, integrity, and public key algorithms used are
- well-known, well-established algorithms.
- o All algorithms are used with cryptographically sound key sizes
- that are believed to provide protection against even the strongest
- cryptanalytic attacks for decades.
- o All algorithms are negotiated, and in case some algorithm is
- broken, it is easy to switch to some other algorithm without
- modifying the base protocol.
-
- Specific concessions were made to make wide-spread fast deployment
- easier. The particular case where this comes up is verifying that
- the server host key really belongs to the desired host; the protocol
- allows the verification to be left out (but this is NOT RECOMMENDED).
- This is believed to significantly improve usability in the short
- term, until widespread Internet public key infrastructures emerge.
-
-4.5 Packet Size and Overhead
-
- Some readers will worry about the increase in packet size due to new
-
-
-
-Ylonen & Moffat Expires March 31, 2004 [Page 6]
-
-Internet-Draft SSH Protocol Architecture Oct 2003
-
-
- headers, padding, and MAC. The minimum packet size is in the order
- of 28 bytes (depending on negotiated algorithms). The increase is
- negligible for large packets, but very significant for one-byte
- packets (telnet-type sessions). There are, however, several factors
- that make this a non-issue in almost all cases:
- o The minimum size of a TCP/IP header is 32 bytes. Thus, the
- increase is actually from 33 to 51 bytes (roughly).
- o The minimum size of the data field of an Ethernet packet is 46
- bytes [RFC-894]. Thus, the increase is no more than 5 bytes. When
- Ethernet headers are considered, the increase is less than 10
- percent.
- o The total fraction of telnet-type data in the Internet is
- negligible, even with increased packet sizes.
-
- The only environment where the packet size increase is likely to have
- a significant effect is PPP [RFC-1134] over slow modem lines (PPP
- compresses the TCP/IP headers, emphasizing the increase in packet
- size). However, with modern modems, the time needed to transfer is in
- the order of 2 milliseconds, which is a lot faster than people can
- type.
-
- There are also issues related to the maximum packet size. To
- minimize delays in screen updates, one does not want excessively
- large packets for interactive sessions. The maximum packet size is
- negotiated separately for each channel.
-
-4.6 Localization and Character Set Support
-
- For the most part, the SSH protocols do not directly pass text that
- would be displayed to the user. However, there are some places where
- such data might be passed. When applicable, the character set for the
- data MUST be explicitly specified. In most places, ISO 10646 with
- UTF-8 encoding is used [RFC-2279]. When applicable, a field is also
- provided for a language tag [RFC-3066].
-
- One big issue is the character set of the interactive session. There
- is no clear solution, as different applications may display data in
- different formats. Different types of terminal emulation may also be
- employed in the client, and the character set to be used is
- effectively determined by the terminal emulation. Thus, no place is
- provided for directly specifying the character set or encoding for
- terminal session data. However, the terminal emulation type (e.g.
- "vt100") is transmitted to the remote site, and it implicitly
- specifies the character set and encoding. Applications typically use
- the terminal type to determine what character set they use, or the
- character set is determined using some external means. The terminal
- emulation may also allow configuring the default character set. In
- any case, the character set for the terminal session is considered
-
-
-
-Ylonen & Moffat Expires March 31, 2004 [Page 7]
-
-Internet-Draft SSH Protocol Architecture Oct 2003
-
-
- primarily a client local issue.
-
- Internal names used to identify algorithms or protocols are normally
- never displayed to users, and must be in US-ASCII.
-
- The client and server user names are inherently constrained by what
- the server is prepared to accept. They might, however, occasionally
- be displayed in logs, reports, etc. They MUST be encoded using ISO
- 10646 UTF-8, but other encodings may be required in some cases. It
- is up to the server to decide how to map user names to accepted user
- names. Straight bit-wise binary comparison is RECOMMENDED.
-
- For localization purposes, the protocol attempts to minimize the
- number of textual messages transmitted. When present, such messages
- typically relate to errors, debugging information, or some externally
- configured data. For data that is normally displayed, it SHOULD be
- possible to fetch a localized message instead of the transmitted
- message by using a numerical code. The remaining messages SHOULD be
- configurable.
-
-5. Data Type Representations Used in the SSH Protocols
- byte
-
- A byte represents an arbitrary 8-bit value (octet) [RFC-1700].
- Fixed length data is sometimes represented as an array of bytes,
- written byte[n], where n is the number of bytes in the array.
-
- boolean
-
- A boolean value is stored as a single byte. The value 0
- represents FALSE, and the value 1 represents TRUE. All non-zero
- values MUST be interpreted as TRUE; however, applications MUST NOT
- store values other than 0 and 1.
-
- uint32
-
- Represents a 32-bit unsigned integer. Stored as four bytes in the
- order of decreasing significance (network byte order). For
- example, the value 699921578 (0x29b7f4aa) is stored as 29 b7 f4
- aa.
-
- uint64
-
- Represents a 64-bit unsigned integer. Stored as eight bytes in
- the order of decreasing significance (network byte order).
-
-
-
-
-
-
-Ylonen & Moffat Expires March 31, 2004 [Page 8]
-
-Internet-Draft SSH Protocol Architecture Oct 2003
-
-
- string
-
- Arbitrary length binary string. Strings are allowed to contain
- arbitrary binary data, including null characters and 8-bit
- characters. They are stored as a uint32 containing its length
- (number of bytes that follow) and zero (= empty string) or more
- bytes that are the value of the string. Terminating null
- characters are not used.
-
- Strings are also used to store text. In that case, US-ASCII is
- used for internal names, and ISO-10646 UTF-8 for text that might
- be displayed to the user. The terminating null character SHOULD
- NOT normally be stored in the string.
-
- For example, the US-ASCII string "testing" is represented as 00 00
- 00 07 t e s t i n g. The UTF8 mapping does not alter the encoding
- of US-ASCII characters.
-
- mpint
-
- Represents multiple precision integers in two's complement format,
- stored as a string, 8 bits per byte, MSB first. Negative numbers
- have the value 1 as the most significant bit of the first byte of
- the data partition. If the most significant bit would be set for a
- positive number, the number MUST be preceded by a zero byte.
- Unnecessary leading bytes with the value 0 or 255 MUST NOT be
- included. The value zero MUST be stored as a string with zero
- bytes of data.
-
- By convention, a number that is used in modular computations in
- Z_n SHOULD be represented in the range 0 <= x < n.
-
- Examples:
- value (hex) representation (hex)
- ---------------------------------------------------------------
- 0 00 00 00 00
- 9a378f9b2e332a7 00 00 00 08 09 a3 78 f9 b2 e3 32 a7
- 80 00 00 00 02 00 80
- -1234 00 00 00 02 ed cc
- -deadbeef 00 00 00 05 ff 21 52 41 11
-
-
-
- name-list
-
- A string containing a comma separated list of names. A name list
- is represented as a uint32 containing its length (number of bytes
- that follow) followed by a comma-separated list of zero or more
-
-
-
-Ylonen & Moffat Expires March 31, 2004 [Page 9]
-
-Internet-Draft SSH Protocol Architecture Oct 2003
-
-
- names. A name MUST be non-zero length, and it MUST NOT contain a
- comma (','). Context may impose additional restrictions on the
- names; for example, the names in a list may have to be valid
- algorithm identifier (see Algorithm Naming below), or [RFC-3066]
- language tags. The order of the names in a list may or may not be
- significant, also depending on the context where the list is is
- used. Terminating NUL characters are not used, neither for the
- individual names, nor for the list as a whole.
-
- Examples:
- value representation (hex)
- ---------------------------------------
- (), the empty list 00 00 00 00
- ("zlib") 00 00 00 04 7a 6c 69 62
- ("zlib", "none") 00 00 00 09 7a 6c 69 62 2c 6e 6f 6e 65
-
-
-
-
-6. Algorithm Naming
-
- The SSH protocols refer to particular hash, encryption, integrity,
- compression, and key exchange algorithms or protocols by names.
- There are some standard algorithms that all implementations MUST
- support. There are also algorithms that are defined in the protocol
- specification but are OPTIONAL. Furthermore, it is expected that
- some organizations will want to use their own algorithms.
-
- In this protocol, all algorithm identifiers MUST be printable
- US-ASCII non-empty strings no longer than 64 characters. Names MUST
- be case-sensitive.
-
- There are two formats for algorithm names:
- o Names that do not contain an at-sign (@) are reserved to be
- assigned by IETF consensus (RFCs). Examples include `3des-cbc',
- `sha-1', `hmac-sha1', and `zlib' (the quotes are not part of the
- name). Names of this format MUST NOT be used without first
- registering them. Registered names MUST NOT contain an at-sign
- (@) or a comma (,).
- o Anyone can define additional algorithms by using names in the
- format name@domainname, e.g. "[email protected]". The
- format of the part preceding the at sign is not specified; it MUST
- consist of US-ASCII characters except at-sign and comma. The part
- following the at-sign MUST be a valid fully qualified internet
- domain name [RFC-1034] controlled by the person or organization
- defining the name. It is up to each domain how it manages its
- local namespace.
-
-
-
-
-Ylonen & Moffat Expires March 31, 2004 [Page 10]
-
-Internet-Draft SSH Protocol Architecture Oct 2003
-
-
-7. Message Numbers
-
- SSH packets have message numbers in the range 1 to 255. These numbers
- have been allocated as follows:
-
-
- Transport layer protocol:
-
- 1 to 19 Transport layer generic (e.g. disconnect, ignore, debug,
- etc.)
- 20 to 29 Algorithm negotiation
- 30 to 49 Key exchange method specific (numbers can be reused for
- different authentication methods)
-
- User authentication protocol:
-
- 50 to 59 User authentication generic
- 60 to 79 User authentication method specific (numbers can be
- reused for different authentication methods)
-
- Connection protocol:
-
- 80 to 89 Connection protocol generic
- 90 to 127 Channel related messages
-
- Reserved for client protocols:
-
- 128 to 191 Reserved
-
- Local extensions:
-
- 192 to 255 Local extensions
-
-
-
-8. IANA Considerations
-
- The initial state of the IANA registry is detailed in [SSH-NUMBERS].
-
- Allocation of the following types of names in the SSH protocols is
- assigned by IETF consensus:
- o SSH encryption algorithm names,
- o SSH MAC algorithm names,
- o SSH public key algorithm names (public key algorithm also implies
- encoding and signature/encryption capability),
- o SSH key exchange method names, and
- o SSH protocol (service) names.
-
-
-
-
-Ylonen & Moffat Expires March 31, 2004 [Page 11]
-
-Internet-Draft SSH Protocol Architecture Oct 2003
-
-
- These names MUST be printable US-ASCII strings, and MUST NOT contain
- the characters at-sign ('@'), comma (','), or whitespace or control
- characters (ASCII codes 32 or less). Names are case-sensitive, and
- MUST NOT be longer than 64 characters.
-
- Names with the at-sign ('@') in them are allocated by the owner of
- DNS name after the at-sign (hierarchical allocation in [RFC-2343]),
- otherwise the same restrictions as above.
-
- Each category of names listed above has a separate namespace.
- However, using the same name in multiple categories SHOULD be avoided
- to minimize confusion.
-
- Message numbers (see Section Message Numbers (Section 7)) in the
- range of 0..191 are allocated via IETF consensus; message numbers in
- the 192..255 range (the "Local extensions" set) are reserved for
- private use.
-
-9. Security Considerations
-
- In order to make the entire body of Security Considerations more
- accessible, Security Considerations for the transport,
- authentication, and connection documents have been gathered here.
-
- The transport protocol [1] provides a confidential channel over an
- insecure network. It performs server host authentication, key
- exchange, encryption, and integrity protection. It also derives a
- unique session id that may be used by higher-level protocols.
-
- The authentication protocol [2] provides a suite of mechanisms which
- can be used to authenticate the client user to the server.
- Individual mechanisms specified in the in authentication protocol use
- the session id provided by the transport protocol and/or depend on
- the security and integrity guarantees of the transport protocol.
-
- The connection protocol [3] specifies a mechanism to multiplex
- multiple streams [channels] of data over the confidential and
- authenticated transport. It also specifies channels for accessing an
- interactive shell, for 'proxy-forwarding' various external protocols
- over the secure transport (including arbitrary TCP/IP protocols), and
- for accessing secure 'subsystems' on the server host.
-
-9.1 Pseudo-Random Number Generation
-
- This protocol binds each session key to the session by including
- random, session specific data in the hash used to produce session
- keys. Special care should be taken to ensure that all of the random
- numbers are of good quality. If the random data here (e.g., DH
-
-
-
-Ylonen & Moffat Expires March 31, 2004 [Page 12]
-
-Internet-Draft SSH Protocol Architecture Oct 2003
-
-
- parameters) are pseudo-random then the pseudo-random number generator
- should be cryptographically secure (i.e., its next output not easily
- guessed even when knowing all previous outputs) and, furthermore,
- proper entropy needs to be added to the pseudo-random number
- generator. RFC 1750 [1750] offers suggestions for sources of random
- numbers and entropy. Implementors should note the importance of
- entropy and the well-meant, anecdotal warning about the difficulty in
- properly implementing pseudo-random number generating functions.
-
- The amount of entropy available to a given client or server may
- sometimes be less than what is required. In this case one must
- either resort to pseudo-random number generation regardless of
- insufficient entropy or refuse to run the protocol. The latter is
- preferable.
-
-9.2 Transport
-
-9.2.1 Confidentiality
-
- It is beyond the scope of this document and the Secure Shell Working
- Group to analyze or recommend specific ciphers other than the ones
- which have been established and accepted within the industry. At the
- time of this writing, ciphers commonly in use include 3DES, ARCFOUR,
- twofish, serpent and blowfish. AES has been accepted by The
- published as a US Federal Information Processing Standards [FIPS-197]
- and the cryptographic community as being acceptable for this purpose
- as well has accepted AES. As always, implementors and users should
- check current literature to ensure that no recent vulnerabilities
- have been found in ciphers used within products. Implementors should
- also check to see which ciphers are considered to be relatively
- stronger than others and should recommend their use to users over
- relatively weaker ciphers. It would be considered good form for an
- implementation to politely and unobtrusively notify a user that a
- stronger cipher is available and should be used when a weaker one is
- actively chosen.
-
- The "none" cipher is provided for debugging and SHOULD NOT be used
- except for that purpose. It's cryptographic properties are
- sufficiently described in RFC 2410, which will show that its use does
- not meet the intent of this protocol.
-
- The relative merits of these and other ciphers may also be found in
- current literature. Two references that may provide information on
- the subject are [SCHNEIER] and [KAUFMAN,PERLMAN,SPECINER]. Both of
- these describe the CBC mode of operation of certain ciphers and the
- weakness of this scheme. Essentially, this mode is theoretically
- vulnerable to chosen cipher-text attacks because of the high
- predictability of the start of packet sequence. However, this attack
-
-
-
-Ylonen & Moffat Expires March 31, 2004 [Page 13]
-
-Internet-Draft SSH Protocol Architecture Oct 2003
-
-
- is still deemed difficult and not considered fully practicable
- especially if relatively longer block sizes are used.
-
- Additionally, another CBC mode attack may be mitigated through the
- insertion of packets containing SSH_MSG_IGNORE. Without this
- technique, a specific attack may be successful. For this attack
- (commonly known as the Rogaway attack
- [ROGAWAY],[DAI],[BELLARE,KOHNO,NAMPREMPRE]) to work, the attacker
- would need to know the IV of the next block that is going to be
- encrypted. In CBC mode that is the output of the encryption of the
- previous block. If the attacker does not have any way to see the
- packet yet (i.e it is in the internal buffers of the ssh
- implementation or even in the kernel) then this attack will not work.
- If the last packet has been sent out to the network (i.e the attacker
- has access to it) then he can use the attack.
-
- In the optimal case an implementor would need to add an extra packet
- only if the packet has been sent out onto the network and there are
- no other packets waiting for transmission. Implementors may wish to
- check to see if there are any unsent packets awaiting transmission,
- but unfortunately it is not normally easy to obtain this information
- from the kernel or buffers. If there are not, then a packet
- containing SSH_MSG_IGNORE SHOULD be sent. If a new packet is added
- to the stream every time the attacker knows the IV that is supposed
- to be used for the next packet, then the attacker will not be able to
- guess the correct IV, thus the attack will never be successfull.
-
- As an example, consider the following case:
-
-
- Client Server
- ------ ------
- TCP(seq=x, len=500) ->
- contains Record 1
-
- [500 ms passes, no ACK]
-
- TCP(seq=x, len=1000) ->
- contains Records 1,2
-
- ACK
-
-
- 1. The Nagle algorithm + TCP retransmits mean that the two records
- get coalesced into a single TCP segment
- 2. Record 2 is *not* at the beginning of the TCP segment and never
- will be, since it gets ACKed.
-
-
-
-
-Ylonen & Moffat Expires March 31, 2004 [Page 14]
-
-Internet-Draft SSH Protocol Architecture Oct 2003
-
-
- 3. Yet, the attack is possible because Record 1 has already been
- seen.
-
- As this example indicates, it's totally unsafe to use the existence
- of unflushed data in the TCP buffers proper as a guide to whether you
- need an empty packet, since when you do the second write(), the
- buffers will contain the un-ACKed Record 1.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Ylonen & Moffat Expires March 31, 2004 [Page 15]
-
-Internet-Draft SSH Protocol Architecture Oct 2003
-
-
- On the other hand, it's perfectly safe to have the following
- situation:
-
-
- Client Server
- ------ ------
- TCP(seq=x, len=500) ->
- contains SSH_MSG_IGNORE
-
- TCP(seq=y, len=500) ->
- contains Data
-
- Provided that the IV for second SSH Record is fixed after the data for
- the Data packet is determined -i.e. you do:
- read from user
- encrypt null packet
- encrypt data packet
-
-
-9.2.2 Data Integrity
-
- This protocol does allow the Data Integrity mechanism to be disabled.
- Implementors SHOULD be wary of exposing this feature for any purpose
- other than debugging. Users and administrators SHOULD be explicitly
- warned anytime the "none" MAC is enabled.
-
- So long as the "none" MAC is not used, this protocol provides data
- integrity.
-
- Because MACs use a 32 bit sequence number, they might start to leak
- information after 2**32 packets have been sent. However, following
- the rekeying recommendations should prevent this attack. The
- transport protocol [1] recommends rekeying after one gigabyte of
- data, and the smallest possible packet is 16 bytes. Therefore,
- rekeying SHOULD happen after 2**28 packets at the very most.
-
-9.2.3 Replay
-
- The use of a MAC other than 'none' provides integrity and
- authentication. In addition, the transport protocol provides a
- unique session identifier (bound in part to pseudo-random data that
- is part of the algorithm and key exchange process) that can be used
- by higher level protocols to bind data to a given session and prevent
- replay of data from prior sessions. For example, the authentication
- protocol uses this to prevent replay of signatures from previous
- sessions. Because public key authentication exchanges are
- cryptographically bound to the session (i.e., to the initial key
- exchange) they cannot be successfully replayed in other sessions.
-
-
-
-Ylonen & Moffat Expires March 31, 2004 [Page 16]
-
-Internet-Draft SSH Protocol Architecture Oct 2003
-
-
- Note that the session ID can be made public without harming the
- security of the protocol.
-
- If two session happen to have the same session ID [hash of key
- exchanges] then packets from one can be replayed against the other.
- It must be stressed that the chances of such an occurrence are,
- needless to say, minimal when using modern cryptographic methods.
- This is all the more so true when specifying larger hash function
- outputs and DH parameters.
-
- Replay detection using monotonically increasing sequence numbers as
- input to the MAC, or HMAC in some cases, is described in [RFC2085] />
- [RFC2246], [RFC2743], [RFC1964], [RFC2025], and [RFC1510]. The
- underlying construct is discussed in [RFC2104]. Essentially a
- different sequence number in each packet ensures that at least this
- one input to the MAC function will be unique and will provide a
- nonrecurring MAC output that is not predictable to an attacker. If
- the session stays active long enough, however, this sequence number
- will wrap. This event may provide an attacker an opportunity to
- replay a previously recorded packet with an identical sequence number
- but only if the peers have not rekeyed since the transmission of the
- first packet with that sequence number. If the peers have rekeyed,
- then the replay will be detected as the MAC check will fail. For
- this reason, it must be emphasized that peers MUST rekey before a
- wrap of the sequence numbers. Naturally, if an attacker does attempt
- to replay a captured packet before the peers have rekeyed, then the
- receiver of the duplicate packet will not be able to validate the MAC
- and it will be discarded. The reason that the MAC will fail is
- because the receiver will formulate a MAC based upon the packet
- contents, the shared secret, and the expected sequence number. Since
- the replayed packet will not be using that expected sequence number
- (the sequence number of the replayed packet will have already been
- passed by the receiver) then the calculated MAC will not match the
- MAC received with the packet.
-
-9.2.4 Man-in-the-middle
-
- This protocol makes no assumptions nor provisions for an
- infrastructure or means for distributing the public keys of hosts. It
- is expected that this protocol will sometimes be used without first
- verifying the association between the server host key and the server
- host name. Such usage is vulnerable to man-in-the-middle attacks.
- This section describes this and encourages administrators and users
- to understand the importance of verifying this association before any
- session is initiated.
-
- There are three cases of man-in-the-middle attacks to consider. The
- first is where an attacker places a device between the client and the
-
-
-
-Ylonen & Moffat Expires March 31, 2004 [Page 17]
-
-Internet-Draft SSH Protocol Architecture Oct 2003
-
-
- server before the session is initiated. In this case, the attack
- device is trying to mimic the legitimate server and will offer its
- public key to the client when the client initiates a session. If it
- were to offer the public key of the server, then it would not be able
- to decrypt or sign the transmissions between the legitimate server
- and the client unless it also had access to the private-key of the
- host. The attack device will also, simultaneously to this, initiate
- a session to the legitimate server masquerading itself as the client.
- If the public key of the server had been securely distributed to the
- client prior to that session initiation, the key offered to the
- client by the attack device will not match the key stored on the
- client. In that case, the user SHOULD be given a warning that the
- offered host key does not match the host key cached on the client.
- As described in Section 3.1 of [ARCH], the user may be free to accept
- the new key and continue the session. It is RECOMMENDED that the
- warning provide sufficient information to the user of the client
- device so they may make an informed decision. If the user chooses to
- continue the session with the stored public-key of the server (not
- the public-key offered at the start of the session), then the session
- specific data between the attacker and server will be different
- between the client-to-attacker session and the attacker-to-server
- sessions due to the randomness discussed above. From this, the
- attacker will not be able to make this attack work since the attacker
- will not be able to correctly sign packets containing this session
- specific data from the server since he does not have the private key
- of that server.
-
- The second case that should be considered is similar to the first
- case in that it also happens at the time of connection but this case
- points out the need for the secure distribution of server public
- keys. If the server public keys are not securely distributed then
- the client cannot know if it is talking to the intended server. An
- attacker may use social engineering techniques to pass off server
- keys to unsuspecting users and may then place a man-in-the-middle
- attack device between the legitimate server and the clients. If this
- is allowed to happen then the clients will form client-to-attacker
- sessions and the attacker will form attacker-to-server sessions and
- will be able to monitor and manipulate all of the traffic between the
- clients and the legitimate servers. Server administrators are
- encouraged to make host key fingerprints available for checking by
- some means whose security does not rely on the integrity of the
- actual host keys. Possible mechanisms are discussed in Section 3.1
- of [SSH-ARCH] and may also include secured Web pages, physical pieces
- of paper, etc. Implementors SHOULD provide recommendations on how
- best to do this with their implementation. Because the protocol is
- extensible, future extensions to the protocol may provide better
- mechanisms for dealing with the need to know the server's host key
- before connecting. For example, making the host key fingerprint
-
-
-
-Ylonen & Moffat Expires March 31, 2004 [Page 18]
-
-Internet-Draft SSH Protocol Architecture Oct 2003
-
-
- available through a secure DNS lookup, or using kerberos over gssapi
- during key exchange to authenticate the server are possibilities.
-
- In the third man-in-the-middle case, attackers may attempt to
- manipulate packets in transit between peers after the session has
- been established. As described in the Replay part of this section, a
- successful attack of this nature is very improbable. As in the
- Replay section, this reasoning does assume that the MAC is secure and
- that it is infeasible to construct inputs to a MAC algorithm to give
- a known output. This is discussed in much greater detail in Section
- 6 of RFC 2104. If the MAC algorithm has a vulnerability or is weak
- enough, then the attacker may be able to specify certain inputs to
- yield a known MAC. With that they may be able to alter the contents
- of a packet in transit. Alternatively the attacker may be able to
- exploit the algorithm vulnerability or weakness to find the shared
- secret by reviewing the MACs from captured packets. In either of
- those cases, an attacker could construct a packet or packets that
- could be inserted into an SSH stream. To prevent that, implementors
- are encouraged to utilize commonly accepted MAC algorithms and
- administrators are encouraged to watch current literature and
- discussions of cryptography to ensure that they are not using a MAC
- algorithm that has a recently found vulnerability or weakness.
-
- In summary, the use of this protocol without a reliable association
- of the binding between a host and its host keys is inherently
- insecure and is NOT RECOMMENDED. It may however be necessary in
- non-security critical environments, and will still provide protection
- against passive attacks. Implementors of protocols and applications
- running on top of this protocol should keep this possibility in mind.
-
-9.2.5 Denial-of-service
-
- This protocol is designed to be used over a reliable transport. If
- transmission errors or message manipulation occur, the connection is
- closed. The connection SHOULD be re-established if this occurs.
- Denial of service attacks of this type ("wire cutter") are almost
- impossible to avoid.
-
- In addition, this protocol is vulnerable to Denial of Service attacks
- because an attacker can force the server to go through the CPU and
- memory intensive tasks of connection setup and key exchange without
- authenticating. Implementors SHOULD provide features that make this
- more difficult. For example, only allowing connections from a subset
- of IPs known to have valid users.
-
-9.2.6 Covert Channels
-
- The protocol was not designed to eliminate covert channels. For
-
-
-
-Ylonen & Moffat Expires March 31, 2004 [Page 19]
-
-Internet-Draft SSH Protocol Architecture Oct 2003
-
-
- example, the padding, SSH_MSG_IGNORE messages, and several other
- places in the protocol can be used to pass covert information, and
- the recipient has no reliable way to verify whether such information
- is being sent.
-
-9.2.7 Forward Secrecy
-
- It should be noted that the Diffie-Hellman key exchanges may provide
- perfect forward secrecy (PFS). PFS is essentially defined as the
- cryptographic property of a key-establishment protocol in which the
- compromise of a session key or long-term private key after a given
- session does not cause the compromise of any earlier session. [ANSI
- T1.523-2001] SSHv2 sessions resulting from a key exchange using
- diffie-hellman-group1-sha1 are secure even if private keying/
- authentication material is later revealed, but not if the session
- keys are revealed. So, given this definition of PFS, SSHv2 does have
- PFS. It is hoped that all other key exchange mechanisms proposed and
- used in the future will also provide PFS. This property is not
- commuted to any of the applications or protocols using SSH as a
- transport however. The transport layer of SSH provides
- confidentiality for password authentication and other methods that
- rely on secret data.
-
- Of course, if the DH private parameters for the client and server are
- revealed then the session key is revealed, but these items can be
- thrown away after the key exchange completes. It's worth pointing
- out that these items should not be allowed to end up on swap space
- and that they should be erased from memory as soon as the key
- exchange completes.
-
-9.3 Authentication Protocol
-
- The purpose of this protocol is to perform client user
- authentication. It assumes that this run over a secure transport
- layer protocol, which has already authenticated the server machine,
- established an encrypted communications channel, and computed a
- unique session identifier for this session.
-
- Several authentication methods with different security
- characteristics are allowed. It is up to the server's local policy
- to decide which methods (or combinations of methods) it is willing to
- accept for each user. Authentication is no stronger than the weakest
- combination allowed.
-
- The server may go into a "sleep" period after repeated unsuccessful
- authentication attempts to make key search more difficult for
- attackers. Care should be taken so that this doesn't become a
- self-denial of service vector.
-
-
-
-Ylonen & Moffat Expires March 31, 2004 [Page 20]
-
-Internet-Draft SSH Protocol Architecture Oct 2003
-
-
-9.3.1 Weak Transport
-
- If the transport layer does not provide confidentiality,
- authentication methods that rely on secret data SHOULD be disabled.
- If it does not provide strong integrity protection, requests to
- change authentication data (e.g. a password change) SHOULD be
- disabled to prevent an attacker from modifying the ciphertext
- without being noticed, or rendering the new authentication data
- unusable (denial of service).
-
- The assumption as stated above that the Authentication Protocol only
- run over a secure transport that has previously authenticated the
- server is very important to note. People deploying SSH are reminded
- of the consequences of man-in-the-middle attacks if the client does
- not have a very strong a priori association of the server with the
- host key of that server. Specifically for the case of the
- Authentication Protocol the client may form a session to a
- man-in-the-middle attack device and divulge user credentials such as
- their username and password. Even in the cases of authentication
- where no user credentials are divulged, an attacker may still gain
- information they shouldn't have by capturing key-strokes in much the
- same way that a honeypot works.
-
-9.3.2 Debug messages
-
- Special care should be taken when designing debug messages. These
- messages may reveal surprising amounts of information about the host
- if not properly designed. Debug messages can be disabled (during
- user authentication phase) if high security is required.
- Administrators of host machines should make all attempts to
- compartmentalize all event notification messages and protect them
- from unwarranted observation. Developers should be aware of the
- sensitive nature of some of the normal event messages and debug
- messages and may want to provide guidance to administrators on ways
- to keep this information away from unauthorized people. Developers
- should consider minimizing the amount of sensitive information
- obtainable by users during the authentication phase in accordance
- with the local policies. For this reason, it is RECOMMENDED that
- debug messages be initially disabled at the time of deployment and
- require an active decision by an administrator to allow them to be
- enabled. It is also RECOMMENDED that a message expressing this
- concern be presented to the administrator of a system when the action
- is taken to enable debugging messages.
-
-9.3.3 Local security policy
-
- Implementer MUST ensure that the credentials provided validate the
- professed user and also MUST ensure that the local policy of the
-
-
-
-Ylonen & Moffat Expires March 31, 2004 [Page 21]
-
-Internet-Draft SSH Protocol Architecture Oct 2003
-
-
- server permits the user the access requested. In particular, because
- of the flexible nature of the SSH connection protocol, it may not be
- possible to determine the local security policy, if any, that should
- apply at the time of authentication because the kind of service being
- requested is not clear at that instant. For example, local policy
- might allow a user to access files on the server, but not start an
- interactive shell. However, during the authentication protocol, it is
- not known whether the user will be accessing files or attempting to
- use an interactive shell, or even both. In any event, where local
- security policy for the server host exists, it MUST be applied and
- enforced correctly.
-
- Implementors are encouraged to provide a default local policy and
- make its parameters known to administrators and users. At the
- discretion of the implementors, this default policy may be along the
- lines of 'anything goes' where there are no restrictions placed upon
- users, or it may be along the lines of 'excessively restrictive' in
- which case the administrators will have to actively make changes to
- this policy to meet their needs. Alternatively, it may be some
- attempt at providing something practical and immediately useful to
- the administrators of the system so they don't have to put in much
- effort to get SSH working. Whatever choice is made MUST be applied
- and enforced as required above.
-
-9.3.4 Public key authentication
-
- The use of public-key authentication assumes that the client host has
- not been compromised. It also assumes that the private-key of the
- server host has not been compromised.
-
- This risk can be mitigated by the use of passphrases on private keys;
- however, this is not an enforceable policy. The use of smartcards,
- or other technology to make passphrases an enforceable policy is
- suggested.
-
- The server could require both password and public-key authentication,
- however, this requires the client to expose its password to the
- server (see section on password authentication below.)
-
-9.3.5 Password authentication
-
- The password mechanism as specified in the authentication protocol
- assumes that the server has not been compromised. If the server has
- been compromised, using password authentication will reveal a valid
- username / password combination to the attacker, which may lead to
- further compromises.
-
- This vulnerability can be mitigated by using an alternative form of
-
-
-
-Ylonen & Moffat Expires March 31, 2004 [Page 22]
-
-Internet-Draft SSH Protocol Architecture Oct 2003
-
-
- authentication. For example, public-key authentication makes no
- assumptions about security on the server.
-
-9.3.6 Host based authentication
-
- Host based authentication assumes that the client has not been
- compromised. There are no mitigating strategies, other than to use
- host based authentication in combination with another authentication
- method.
-
-9.4 Connection protocol
-
-9.4.1 End point security
-
- End point security is assumed by the connection protocol. If the
- server has been compromised, any terminal sessions, port forwarding,
- or systems accessed on the host are compromised. There are no
- mitigating factors for this.
-
- If the client end point has been compromised, and the server fails to
- stop the attacker at the authentication protocol, all services
- exposed (either as subsystems or through forwarding) will be
- vulnerable to attack. Implementors SHOULD provide mechanisms for
- administrators to control which services are exposed to limit the
- vulnerability of other services.
-
- These controls might include controlling which machines and ports can
- be target in 'port-forwarding' operations, which users are allowed to
- use interactive shell facilities, or which users are allowed to use
- exposed subsystems.
-
-9.4.2 Proxy forwarding
-
- The SSH connection protocol allows for proxy forwarding of other
- protocols such as SNMP, POP3, and HTTP. This may be a concern for
- network administrators who wish to control the access of certain
- applications by users located outside of their physical location.
- Essentially, the forwarding of these protocols may violate site
- specific security policies as they may be undetectably tunneled
- through a firewall. Implementors SHOULD provide an administrative
- mechanism to control the proxy forwarding functionality so that site
- specific security policies may be upheld.
-
- In addition, a reverse proxy forwarding functionality is available,
- which again can be used to bypass firewall controls.
-
- As indicated above, end-point security is assumed during proxy
- forwarding operations. Failure of end-point security will compromise
-
-
-
-Ylonen & Moffat Expires March 31, 2004 [Page 23]
-
-Internet-Draft SSH Protocol Architecture Oct 2003
-
-
- all data passed over proxy forwarding.
-
-9.4.3 X11 forwarding
-
- Another form of proxy forwarding provided by the ssh connection
- protocol is the forwarding of the X11 protocol. If end-point
- security has been compromised, X11 forwarding may allow attacks
- against the X11 server. Users and administrators should, as a matter
- of course, use appropriate X11 security mechanisms to prevent
- unauthorized use of the X11 server. Implementors, administrators and
- users who wish to further explore the security mechanisms of X11 are
- invited to read [SCHEIFLER] and analyze previously reported problems
- with the interactions between SSH forwarding and X11 in CERT
- vulnerabilities VU#363181 and VU#118892 [CERT].
-
- X11 display forwarding with SSH, by itself, is not sufficient to
- correct well known problems with X11 security [VENEMA]. However, X11
- display forwarding in SSHv2 (or other, secure protocols), combined
- with actual and pseudo-displays which accept connections only over
- local IPC mechanisms authorized by permissions or ACLs, does correct
- many X11 security problems as long as the "none" MAC is not used. It
- is RECOMMENDED that X11 display implementations default to allowing
- display opens only over local IPC. It is RECOMMENDED that SSHv2
- server implementations that support X11 forwarding default to
- allowing display opens only over local IPC. On single-user systems
- it might be reasonable to default to allowing local display opens
- over TCP/IP.
-
- Implementors of the X11 forwarding protocol SHOULD implement the
- magic cookie access checking spoofing mechanism as described in
- [ssh-connect] as an additional mechanism to prevent unauthorized use
- of the proxy.
-
-Normative References
-
- [SSH-ARCH]
- Ylonen, T., "SSH Protocol Architecture", I-D
- draft-ietf-architecture-15.txt, Oct 2003.
-
- [SSH-TRANS]
- Ylonen, T., "SSH Transport Layer Protocol", I-D
- draft-ietf-transport-17.txt, Oct 2003.
-
- [SSH-USERAUTH]
- Ylonen, T., "SSH Authentication Protocol", I-D
- draft-ietf-userauth-18.txt, Oct 2003.
-
- [SSH-CONNECT]
-
-
-
-Ylonen & Moffat Expires March 31, 2004 [Page 24]
-
-Internet-Draft SSH Protocol Architecture Oct 2003
-
-
- Ylonen, T., "SSH Connection Protocol", I-D
- draft-ietf-connect-18.txt, Oct 2003.
-
- [SSH-NUMBERS]
- Lehtinen, S. and D. Moffat, "SSH Protocol Assigned
- Numbers", I-D draft-ietf-secsh-assignednumbers-05.txt, Oct
- 2003.
-
- [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
- Requirement Levels", BCP 14, RFC 2119, March 1997.
-
-Informative References
-
- [FIPS-186]
- Federal Information Processing Standards Publication,
- "FIPS PUB 186, Digital Signature Standard", May 1994.
-
- [FIPS-197]
- National Institue of Standards and Technology, "FIPS 197,
- Specification for the Advanced Encryption Standard",
- November 2001.
-
- [ANSI T1.523-2001]
- American National Standards Insitute, Inc., "Telecom
- Glossary 2000", February 2001.
-
- [SCHEIFLER]
- Scheifler, R., "X Window System : The Complete Reference
- to Xlib, X Protocol, Icccm, Xlfd, 3rd edition.", Digital
- Press ISBN 1555580882, Feburary 1992.
-
- [RFC0854] Postel, J. and J. Reynolds, "Telnet Protocol
- Specification", STD 8, RFC 854, May 1983.
-
- [RFC0894] Hornig, C., "Standard for the transmission of IP datagrams
- over Ethernet networks", STD 41, RFC 894, April 1984.
-
- [RFC1034] Mockapetris, P., "Domain names - concepts and facilities",
- STD 13, RFC 1034, November 1987.
-
- [RFC1134] Perkins, D., "Point-to-Point Protocol: A proposal for
- multi-protocol transmission of datagrams over
- Point-to-Point links", RFC 1134, November 1989.
-
- [RFC1282] Kantor, B., "BSD Rlogin", RFC 1282, December 1991.
-
- [RFC1510] Kohl, J. and B. Neuman, "The Kerberos Network
- Authentication Service (V5)", RFC 1510, September 1993.
-
-
-
-Ylonen & Moffat Expires March 31, 2004 [Page 25]
-
-Internet-Draft SSH Protocol Architecture Oct 2003
-
-
- [RFC1700] Reynolds, J. and J. Postel, "Assigned Numbers", RFC 1700,
- October 1994.
-
- [RFC1750] Eastlake, D., Crocker, S. and J. Schiller, "Randomness
- Recommendations for Security", RFC 1750, December 1994.
-
- [RFC3066] Alvestrand, H., "Tags for the Identification of
- Languages", BCP 47, RFC 3066, January 2001.
-
- [RFC1964] Linn, J., "The Kerberos Version 5 GSS-API Mechanism", RFC
- 1964, June 1996.
-
- [RFC2025] Adams, C., "The Simple Public-Key GSS-API Mechanism
- (SPKM)", RFC 2025, October 1996.
-
- [RFC2085] Oehler, M. and R. Glenn, "HMAC-MD5 IP Authentication with
- Replay Prevention", RFC 2085, February 1997.
-
- [RFC2104] Krawczyk, H., Bellare, M. and R. Canetti, "HMAC:
- Keyed-Hashing for Message Authentication", RFC 2104,
- February 1997.
-
- [RFC2246] Dierks, T., Allen, C., Treese, W., Karlton, P., Freier, A.
- and P. Kocher, "The TLS Protocol Version 1.0", RFC 2246,
- January 1999.
-
- [RFC2279] Yergeau, F., "UTF-8, a transformation format of ISO
- 10646", RFC 2279, January 1998.
-
- [RFC2410] Glenn, R. and S. Kent, "The NULL Encryption Algorithm and
- Its Use With IPsec", RFC 2410, November 1998.
-
- [RFC2434] Narten, T. and H. Alvestrand, "Guidelines for Writing an
- IANA Considerations Section in RFCs", BCP 26, RFC 2434,
- October 1998.
-
- [RFC2743] Linn, J., "Generic Security Service Application Program
- Interface Version 2, Update 1", RFC 2743, January 2000.
-
- [SCHNEIER]
- Schneier, B., "Applied Cryptography Second Edition:
- protocols algorithms and source in code in C", 1996.
-
- [KAUFMAN,PERLMAN,SPECINER]
- Kaufman, C., Perlman, R. and M. Speciner, "Network
- Security: PRIVATE Communication in a PUBLIC World", 1995.
-
- [CERT] CERT Coordination Center, The., "http://www.cert.org/nav/
-
-
-
-Ylonen & Moffat Expires March 31, 2004 [Page 26]
-
-Internet-Draft SSH Protocol Architecture Oct 2003
-
-
- index_red.html".
-
- [VENEMA] Venema, W., "Murphy's Law and Computer Security",
- Proceedings of 6th USENIX Security Symposium, San Jose CA
- http://www.usenix.org/publications/library/proceedings/
- sec96/venema.html, July 1996.
-
- [ROGAWAY] Rogaway, P., "Problems with Proposed IP Cryptography",
- Unpublished paper http://www.cs.ucdavis.edu/~rogaway/
- papers/draft-rogaway-ipsec-comments-00.txt, 1996.
-
- [DAI] Dai, W., "An attack against SSH2 protocol", Email to the
- SECSH Working Group [email protected] ftp://
- ftp.ietf.org/ietf-mail-archive/secsh/2002-02.mail, Feb
- 2002.
-
- [BELLARE,KOHNO,NAMPREMPRE]
- Bellaire, M., Kohno, T. and C. Namprempre, "Authenticated
- Encryption in SSH: Fixing the SSH Binary Packet Protocol",
- , Sept 2002.
-
-
-Authors' Addresses
-
- Tatu Ylonen
- SSH Communications Security Corp
- Fredrikinkatu 42
- HELSINKI FIN-00100
- Finland
-
-
-
- Darren J. Moffat (editor)
- Sun Microsystems, Inc
- 17 Network Circle
- Menlo Park CA 94025
- USA
-
-
-
-
-
-
-
-
-
-
-
-
-Ylonen & Moffat Expires March 31, 2004 [Page 27]
-
-Internet-Draft SSH Protocol Architecture Oct 2003
-
-
-Intellectual Property Statement
-
- The IETF takes no position regarding the validity or scope of any
- intellectual property or other rights that might be claimed to
- pertain to the implementation or use of the technology described in
- this document or the extent to which any license under such rights
- might or might not be available; neither does it represent that it
- has made any effort to identify any such rights. Information on the
- IETF's procedures with respect to rights in standards-track and
- standards-related documentation can be found in BCP-11. Copies of
- claims of rights made available for publication and any assurances of
- licenses to be made available, or the result of an attempt made to
- obtain a general license or permission for the use of such
- proprietary rights by implementors or users of this specification can
- be obtained from the IETF Secretariat.
-
- The IETF invites any interested party to bring to its attention any
- copyrights, patents or patent applications, or other proprietary
- rights which may cover technology that may be required to practice
- this standard. Please address the information to the IETF Executive
- Director.
-
- The IETF has been notified of intellectual property rights claimed in
- regard to some or all of the specification contained in this
- document. For more information consult the online list of claimed
- rights.
-
-
-Full Copyright Statement
-
- Copyright (C) The Internet Society (2003). All Rights Reserved.
-
- This document and translations of it may be copied and furnished to
- others, and derivative works that comment on or otherwise explain it
- or assist in its implementation may be prepared, copied, published
- and distributed, in whole or in part, without restriction of any
- kind, provided that the above copyright notice and this paragraph are
- included on all such copies and derivative works. However, this
- document itself may not be modified in any way, such as by removing
- the copyright notice or references to the Internet Society or other
- Internet organizations, except as needed for the purpose of
- developing Internet standards in which case the procedures for
- copyrights defined in the Internet Standards process must be
- followed, or as required to translate it into languages other than
- English.
-
- The limited permissions granted above are perpetual and will not be
- revoked by the Internet Society or its successors or assignees.
-
-
-
-Ylonen & Moffat Expires March 31, 2004 [Page 28]
-
-Internet-Draft SSH Protocol Architecture Oct 2003
-
-
- This document and the information contained herein is provided on an
- "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
- TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
- BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
- HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
- MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
-
-
-Acknowledgment
-
- Funding for the RFC Editor function is currently provided by the
- Internet Society.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Ylonen & Moffat Expires March 31, 2004 [Page 29] \ No newline at end of file
diff --git a/lib/ssh/doc/standard/draft-ietf-secsh-connect-18.2.ps b/lib/ssh/doc/standard/draft-ietf-secsh-connect-18.2.ps
deleted file mode 100644
index 7a386724c2..0000000000
--- a/lib/ssh/doc/standard/draft-ietf-secsh-connect-18.2.ps
+++ /dev/null
@@ -1,2557 +0,0 @@
-%!PS-Adobe-3.0
-%%BoundingBox: 75 0 595 747
-%%Title: Enscript Output
-%%For: Magnus Thoang
-%%Creator: GNU enscript 1.6.1
-%%CreationDate: Fri Oct 31 13:33:02 2003
-%%Orientation: Portrait
-%%Pages: 11 0
-%%DocumentMedia: A4 595 842 0 () ()
-%%DocumentNeededResources: (atend)
-%%EndComments
-%%BeginProlog
-%%BeginProcSet: PStoPS 1 15
-userdict begin
-[/showpage/erasepage/copypage]{dup where{pop dup load
- type/operatortype eq{1 array cvx dup 0 3 index cvx put
- bind def}{pop}ifelse}{pop}ifelse}forall
-[/letter/legal/executivepage/a4/a4small/b5/com10envelope
- /monarchenvelope/c5envelope/dlenvelope/lettersmall/note
- /folio/quarto/a5]{dup where{dup wcheck{exch{}put}
- {pop{}def}ifelse}{pop}ifelse}forall
-/setpagedevice {pop}bind 1 index where{dup wcheck{3 1 roll put}
- {pop def}ifelse}{def}ifelse
-/PStoPSmatrix matrix currentmatrix def
-/PStoPSxform matrix def/PStoPSclip{clippath}def
-/defaultmatrix{PStoPSmatrix exch PStoPSxform exch concatmatrix}bind def
-/initmatrix{matrix defaultmatrix setmatrix}bind def
-/initclip[{matrix currentmatrix PStoPSmatrix setmatrix
- [{currentpoint}stopped{$error/newerror false put{newpath}}
- {/newpath cvx 3 1 roll/moveto cvx 4 array astore cvx}ifelse]
- {[/newpath cvx{/moveto cvx}{/lineto cvx}
- {/curveto cvx}{/closepath cvx}pathforall]cvx exch pop}
- stopped{$error/errorname get/invalidaccess eq{cleartomark
- $error/newerror false put cvx exec}{stop}ifelse}if}bind aload pop
- /initclip dup load dup type dup/operatortype eq{pop exch pop}
- {dup/arraytype eq exch/packedarraytype eq or
- {dup xcheck{exch pop aload pop}{pop cvx}ifelse}
- {pop cvx}ifelse}ifelse
- {newpath PStoPSclip clip newpath exec setmatrix} bind aload pop]cvx def
-/initgraphics{initmatrix newpath initclip 1 setlinewidth
- 0 setlinecap 0 setlinejoin []0 setdash 0 setgray
- 10 setmiterlimit}bind def
-end
-%%EndProcSet
-%%BeginResource: procset Enscript-Prolog 1.6 1
-%
-% Procedures.
-%
-
-/_S { % save current state
- /_s save def
-} def
-/_R { % restore from saved state
- _s restore
-} def
-
-/S { % showpage protecting gstate
- gsave
- showpage
- grestore
-} bind def
-
-/MF { % fontname newfontname -> - make a new encoded font
- /newfontname exch def
- /fontname exch def
-
- /fontdict fontname findfont def
- /newfont fontdict maxlength dict def
-
- fontdict {
- exch
- dup /FID eq {
- % skip FID pair
- pop pop
- } {
- % copy to the new font dictionary
- exch newfont 3 1 roll put
- } ifelse
- } forall
-
- newfont /FontName newfontname put
-
- % insert only valid encoding vectors
- encoding_vector length 256 eq {
- newfont /Encoding encoding_vector put
- } if
-
- newfontname newfont definefont pop
-} def
-
-/SF { % fontname width height -> - set a new font
- /height exch def
- /width exch def
-
- findfont
- [width 0 0 height 0 0] makefont setfont
-} def
-
-/SUF { % fontname width height -> - set a new user font
- /height exch def
- /width exch def
-
- /F-gs-user-font MF
- /F-gs-user-font width height SF
-} def
-
-/M {moveto} bind def
-/s {show} bind def
-
-/Box { % x y w h -> - define box path
- /d_h exch def /d_w exch def /d_y exch def /d_x exch def
- d_x d_y moveto
- d_w 0 rlineto
- 0 d_h rlineto
- d_w neg 0 rlineto
- closepath
-} def
-
-/bgs { % x y height blskip gray str -> - show string with bg color
- /str exch def
- /gray exch def
- /blskip exch def
- /height exch def
- /y exch def
- /x exch def
-
- gsave
- x y blskip sub str stringwidth pop height Box
- gray setgray
- fill
- grestore
- x y M str s
-} def
-
-% Highlight bars.
-/highlight_bars { % nlines lineheight output_y_margin gray -> -
- gsave
- setgray
- /ymarg exch def
- /lineheight exch def
- /nlines exch def
-
- % This 2 is just a magic number to sync highlight lines to text.
- 0 d_header_y ymarg sub 2 sub translate
-
- /cw d_output_w cols div def
- /nrows d_output_h ymarg 2 mul sub lineheight div cvi def
-
- % for each column
- 0 1 cols 1 sub {
- cw mul /xp exch def
-
- % for each rows
- 0 1 nrows 1 sub {
- /rn exch def
- rn lineheight mul neg /yp exch def
- rn nlines idiv 2 mod 0 eq {
- % Draw highlight bar. 4 is just a magic indentation.
- xp 4 add yp cw 8 sub lineheight neg Box fill
- } if
- } for
- } for
-
- grestore
-} def
-
-% Line highlight bar.
-/line_highlight { % x y width height gray -> -
- gsave
- /gray exch def
- Box gray setgray fill
- grestore
-} def
-
-% Column separator lines.
-/column_lines {
- gsave
- .1 setlinewidth
- 0 d_footer_h translate
- /cw d_output_w cols div def
- 1 1 cols 1 sub {
- cw mul 0 moveto
- 0 d_output_h rlineto stroke
- } for
- grestore
-} def
-
-% Column borders.
-/column_borders {
- gsave
- .1 setlinewidth
- 0 d_footer_h moveto
- 0 d_output_h rlineto
- d_output_w 0 rlineto
- 0 d_output_h neg rlineto
- closepath stroke
- grestore
-} def
-
-% Do the actual underlay drawing
-/draw_underlay {
- ul_style 0 eq {
- ul_str true charpath stroke
- } {
- ul_str show
- } ifelse
-} def
-
-% Underlay
-/underlay { % - -> -
- gsave
- 0 d_page_h translate
- d_page_h neg d_page_w atan rotate
-
- ul_gray setgray
- ul_font setfont
- /dw d_page_h dup mul d_page_w dup mul add sqrt def
- ul_str stringwidth pop dw exch sub 2 div ul_h_ptsize -2 div moveto
- draw_underlay
- grestore
-} def
-
-/user_underlay { % - -> -
- gsave
- ul_x ul_y translate
- ul_angle rotate
- ul_gray setgray
- ul_font setfont
- 0 0 ul_h_ptsize 2 div sub moveto
- draw_underlay
- grestore
-} def
-
-% Page prefeed
-/page_prefeed { % bool -> -
- statusdict /prefeed known {
- statusdict exch /prefeed exch put
- } {
- pop
- } ifelse
-} def
-
-% Wrapped line markers
-/wrapped_line_mark { % x y charwith charheight type -> -
- /type exch def
- /h exch def
- /w exch def
- /y exch def
- /x exch def
-
- type 2 eq {
- % Black boxes (like TeX does)
- gsave
- 0 setlinewidth
- x w 4 div add y M
- 0 h rlineto w 2 div 0 rlineto 0 h neg rlineto
- closepath fill
- grestore
- } {
- type 3 eq {
- % Small arrows
- gsave
- .2 setlinewidth
- x w 2 div add y h 2 div add M
- w 4 div 0 rlineto
- x w 4 div add y lineto stroke
-
- x w 4 div add w 8 div add y h 4 div add M
- x w 4 div add y lineto
- w 4 div h 8 div rlineto stroke
- grestore
- } {
- % do nothing
- } ifelse
- } ifelse
-} def
-
-% EPSF import.
-
-/BeginEPSF {
- /b4_Inc_state save def % Save state for cleanup
- /dict_count countdictstack def % Count objects on dict stack
- /op_count count 1 sub def % Count objects on operand stack
- userdict begin
- /showpage { } def
- 0 setgray 0 setlinecap
- 1 setlinewidth 0 setlinejoin
- 10 setmiterlimit [ ] 0 setdash newpath
- /languagelevel where {
- pop languagelevel
- 1 ne {
- false setstrokeadjust false setoverprint
- } if
- } if
-} bind def
-
-/EndEPSF {
- count op_count sub { pos } repeat % Clean up stacks
- countdictstack dict_count sub { end } repeat
- b4_Inc_state restore
-} bind def
-
-% Check PostScript language level.
-/languagelevel where {
- pop /gs_languagelevel languagelevel def
-} {
- /gs_languagelevel 1 def
-} ifelse
-%%EndResource
-%%BeginResource: procset Enscript-Encoding-88591 1.6 1
-/encoding_vector [
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/space /exclam /quotedbl /numbersign
-/dollar /percent /ampersand /quoteright
-/parenleft /parenright /asterisk /plus
-/comma /hyphen /period /slash
-/zero /one /two /three
-/four /five /six /seven
-/eight /nine /colon /semicolon
-/less /equal /greater /question
-/at /A /B /C
-/D /E /F /G
-/H /I /J /K
-/L /M /N /O
-/P /Q /R /S
-/T /U /V /W
-/X /Y /Z /bracketleft
-/backslash /bracketright /asciicircum /underscore
-/quoteleft /a /b /c
-/d /e /f /g
-/h /i /j /k
-/l /m /n /o
-/p /q /r /s
-/t /u /v /w
-/x /y /z /braceleft
-/bar /braceright /tilde /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/space /exclamdown /cent /sterling
-/currency /yen /brokenbar /section
-/dieresis /copyright /ordfeminine /guillemotleft
-/logicalnot /hyphen /registered /macron
-/degree /plusminus /twosuperior /threesuperior
-/acute /mu /paragraph /bullet
-/cedilla /onesuperior /ordmasculine /guillemotright
-/onequarter /onehalf /threequarters /questiondown
-/Agrave /Aacute /Acircumflex /Atilde
-/Adieresis /Aring /AE /Ccedilla
-/Egrave /Eacute /Ecircumflex /Edieresis
-/Igrave /Iacute /Icircumflex /Idieresis
-/Eth /Ntilde /Ograve /Oacute
-/Ocircumflex /Otilde /Odieresis /multiply
-/Oslash /Ugrave /Uacute /Ucircumflex
-/Udieresis /Yacute /Thorn /germandbls
-/agrave /aacute /acircumflex /atilde
-/adieresis /aring /ae /ccedilla
-/egrave /eacute /ecircumflex /edieresis
-/igrave /iacute /icircumflex /idieresis
-/eth /ntilde /ograve /oacute
-/ocircumflex /otilde /odieresis /divide
-/oslash /ugrave /uacute /ucircumflex
-/udieresis /yacute /thorn /ydieresis
-] def
-%%EndResource
-%%EndProlog
-%%BeginSetup
-%%IncludeResource: font Courier-Bold
-%%IncludeResource: font Courier
-/HFpt_w 10 def
-/HFpt_h 10 def
-/Courier-Bold /HF-gs-font MF
-/HF /HF-gs-font findfont [HFpt_w 0 0 HFpt_h 0 0] makefont def
-/Courier /F-gs-font MF
-/F-gs-font 10 10 SF
-/#copies 1 def
-/d_page_w 520 def
-/d_page_h 747 def
-/d_header_x 0 def
-/d_header_y 747 def
-/d_header_w 520 def
-/d_header_h 0 def
-/d_footer_x 0 def
-/d_footer_y 0 def
-/d_footer_w 520 def
-/d_footer_h 0 def
-/d_output_w 520 def
-/d_output_h 747 def
-/cols 1 def
-userdict/PStoPSxform PStoPSmatrix matrix currentmatrix
- matrix invertmatrix matrix concatmatrix
- matrix invertmatrix put
-%%EndSetup
-%%Page: (0,1) 1
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 1 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 701 M
-(Network Working Group T. Ylonen) s
-5 690 M
-(Internet-Draft SSH Communications Security Corp) s
-5 679 M
-(Expires: March 31, 2004 D. Moffat, Editor, Ed.) s
-5 668 M
-( Sun Microsystems, Inc) s
-5 657 M
-( Oct 2003) s
-5 624 M
-( SSH Connection Protocol) s
-5 613 M
-( draft-ietf-secsh-connect-18.txt) s
-5 591 M
-(Status of this Memo) s
-5 569 M
-( This document is an Internet-Draft and is in full conformance with) s
-5 558 M
-( all provisions of Section 10 of RFC2026.) s
-5 536 M
-( Internet-Drafts are working documents of the Internet Engineering) s
-5 525 M
-( Task Force \(IETF\), its areas, and its working groups. Note that other) s
-5 514 M
-( groups may also distribute working documents as Internet-Drafts.) s
-5 492 M
-( Internet-Drafts are draft documents valid for a maximum of six months) s
-5 481 M
-( and may be updated, replaced, or obsoleted by other documents at any) s
-5 470 M
-( time. It is inappropriate to use Internet-Drafts as reference) s
-5 459 M
-( material or to cite them other than as "work in progress.") s
-5 437 M
-( The list of current Internet-Drafts can be accessed at http://) s
-5 426 M
-( www.ietf.org/ietf/1id-abstracts.txt.) s
-5 404 M
-( The list of Internet-Draft Shadow Directories can be accessed at) s
-5 393 M
-( http://www.ietf.org/shadow.html.) s
-5 371 M
-( This Internet-Draft will expire on March 31, 2004.) s
-5 349 M
-(Copyright Notice) s
-5 327 M
-( Copyright \(C\) The Internet Society \(2003\). All Rights Reserved.) s
-5 305 M
-(Abstract) s
-5 283 M
-( SSH is a protocol for secure remote login and other secure network) s
-5 272 M
-( services over an insecure network.) s
-5 250 M
-( This document describes the SSH Connection Protocol. It provides) s
-5 239 M
-( interactive login sessions, remote execution of commands, forwarded) s
-5 228 M
-( TCP/IP connections, and forwarded X11 connections. All of these) s
-5 217 M
-( channels are multiplexed into a single encrypted tunnel.) s
-5 195 M
-( The SSH Connection Protocol has been designed to run on top of the) s
-5 184 M
-( SSH transport layer and user authentication protocols.) s
-5 129 M
-(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 1]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 2 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Connection Protocol Oct 2003) s
-5 690 M
-(Table of Contents) s
-5 668 M
-( 1. Contributors . . . . . . . . . . . . . . . . . . . . . . . . 3) s
-5 657 M
-( 2. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3) s
-5 646 M
-( 3. Conventions Used in This Document . . . . . . . . . . . . . 3) s
-5 635 M
-( 4. Global Requests . . . . . . . . . . . . . . . . . . . . . . 3) s
-5 624 M
-( 5. Channel Mechanism . . . . . . . . . . . . . . . . . . . . . 4) s
-5 613 M
-( 5.1 Opening a Channel . . . . . . . . . . . . . . . . . . . . . 4) s
-5 602 M
-( 5.2 Data Transfer . . . . . . . . . . . . . . . . . . . . . . . 5) s
-5 591 M
-( 5.3 Closing a Channel . . . . . . . . . . . . . . . . . . . . . 6) s
-5 580 M
-( 5.4 Channel-Specific Requests . . . . . . . . . . . . . . . . . 7) s
-5 569 M
-( 6. Interactive Sessions . . . . . . . . . . . . . . . . . . . . 8) s
-5 558 M
-( 6.1 Opening a Session . . . . . . . . . . . . . . . . . . . . . 8) s
-5 547 M
-( 6.2 Requesting a Pseudo-Terminal . . . . . . . . . . . . . . . . 8) s
-5 536 M
-( 6.3 X11 Forwarding . . . . . . . . . . . . . . . . . . . . . . . 9) s
-5 525 M
-( 6.3.1 Requesting X11 Forwarding . . . . . . . . . . . . . . . . . 9) s
-5 514 M
-( 6.3.2 X11 Channels . . . . . . . . . . . . . . . . . . . . . . . . 10) s
-5 503 M
-( 6.4 Environment Variable Passing . . . . . . . . . . . . . . . . 10) s
-5 492 M
-( 6.5 Starting a Shell or a Command . . . . . . . . . . . . . . . 10) s
-5 481 M
-( 6.6 Session Data Transfer . . . . . . . . . . . . . . . . . . . 11) s
-5 470 M
-( 6.7 Window Dimension Change Message . . . . . . . . . . . . . . 12) s
-5 459 M
-( 6.8 Local Flow Control . . . . . . . . . . . . . . . . . . . . . 12) s
-5 448 M
-( 6.9 Signals . . . . . . . . . . . . . . . . . . . . . . . . . . 12) s
-5 437 M
-( 6.10 Returning Exit Status . . . . . . . . . . . . . . . . . . . 13) s
-5 426 M
-( 7. TCP/IP Port Forwarding . . . . . . . . . . . . . . . . . . . 14) s
-5 415 M
-( 7.1 Requesting Port Forwarding . . . . . . . . . . . . . . . . . 14) s
-5 404 M
-( 7.2 TCP/IP Forwarding Channels . . . . . . . . . . . . . . . . . 15) s
-5 393 M
-( 8. Encoding of Terminal Modes . . . . . . . . . . . . . . . . . 16) s
-5 382 M
-( 9. Summary of Message Numbers . . . . . . . . . . . . . . . . . 18) s
-5 371 M
-( 10. Security Considerations . . . . . . . . . . . . . . . . . . 18) s
-5 360 M
-( 11. iana cONSiderations . . . . . . . . . . . . . . . . . . . . 19) s
-5 349 M
-( 12. Intellectual Property . . . . . . . . . . . . . . . . . . . 19) s
-5 338 M
-( Normative References . . . . . . . . . . . . . . . . . . . . 19) s
-5 327 M
-( Informative References . . . . . . . . . . . . . . . . . . . 20) s
-5 316 M
-( Authors' Addresses . . . . . . . . . . . . . . . . . . . . . 20) s
-5 305 M
-( Intellectual Property and Copyright Statements . . . . . . . 21) s
-5 129 M
-(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 2]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (2,3) 2
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 3 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Connection Protocol Oct 2003) s
-5 690 M
-(1. Contributors) s
-5 668 M
-( The major original contributors of this document were: Tatu Ylonen,) s
-5 657 M
-( Tero Kivinen, Timo J. Rinne, Sami Lehtinen \(all of SSH Communications) s
-5 646 M
-( Security Corp\), and Markku-Juhani O. Saarinen \(University of) s
-5 635 M
-( Jyvaskyla\)) s
-5 613 M
-( The document editor is: [email protected]. Comments on this) s
-5 602 M
-( internet draft should be sent to the IETF SECSH working group,) s
-5 591 M
-( details at: http://ietf.org/html.charters/secsh-charter.html) s
-5 569 M
-(2. Introduction) s
-5 547 M
-( The SSH Connection Protocol has been designed to run on top of the) s
-5 536 M
-( SSH transport layer and user authentication protocols. It provides) s
-5 525 M
-( interactive login sessions, remote execution of commands, forwarded) s
-5 514 M
-( TCP/IP connections, and forwarded X11 connections. The service name) s
-5 503 M
-( for this protocol is "ssh-connection".) s
-5 481 M
-( This document should be read only after reading the SSH architecture) s
-5 470 M
-( document [SSH-ARCH]. This document freely uses terminology and) s
-5 459 M
-( notation from the architecture document without reference or further) s
-5 448 M
-( explanation.) s
-5 426 M
-(3. Conventions Used in This Document) s
-5 404 M
-( The keywords "MUST", "MUST NOT", "REQUIRED", "SHOULD", "SHOULD NOT",) s
-5 393 M
-( and "MAY" that appear in this document are to be interpreted as) s
-5 382 M
-( described in [RFC2119].) s
-5 360 M
-( The used data types and terminology are specified in the architecture) s
-5 349 M
-( document [SSH-ARCH].) s
-5 327 M
-( The architecture document also discusses the algorithm naming) s
-5 316 M
-( conventions that MUST be used with the SSH protocols.) s
-5 294 M
-(4. Global Requests) s
-5 272 M
-( There are several kinds of requests that affect the state of the) s
-5 261 M
-( remote end "globally", independent of any channels. An example is a) s
-5 250 M
-( request to start TCP/IP forwarding for a specific port. All such) s
-5 239 M
-( requests use the following format.) s
-5 217 M
-( byte SSH_MSG_GLOBAL_REQUEST) s
-5 206 M
-( string request name \(restricted to US-ASCII\)) s
-5 195 M
-( boolean want reply) s
-5 184 M
-( ... request-specific data follows) s
-5 129 M
-(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 3]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 4 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Connection Protocol Oct 2003) s
-5 690 M
-( Request names follow the DNS extensibility naming convention outlined) s
-5 679 M
-( in [SSH-ARCH].) s
-5 657 M
-( The recipient will respond to this message with) s
-5 646 M
-( SSH_MSG_REQUEST_SUCCESS or SSH_MSG_REQUEST_FAILURE if `want reply' is) s
-5 635 M
-( TRUE.) s
-5 613 M
-( byte SSH_MSG_REQUEST_SUCCESS) s
-5 602 M
-( ..... response specific data) s
-5 580 M
-( Usually the response specific data is non-existent.) s
-5 558 M
-( If the recipient does not recognize or support the request, it simply) s
-5 547 M
-( responds with SSH_MSG_REQUEST_FAILURE.) s
-5 525 M
-( byte SSH_MSG_REQUEST_FAILURE) s
-5 492 M
-(5. Channel Mechanism) s
-5 470 M
-( All terminal sessions, forwarded connections, etc. are channels.) s
-5 459 M
-( Either side may open a channel. Multiple channels are multiplexed) s
-5 448 M
-( into a single connection.) s
-5 426 M
-( Channels are identified by numbers at each end. The number referring) s
-5 415 M
-( to a channel may be different on each side. Requests to open a) s
-5 404 M
-( channel contain the sender's channel number. Any other) s
-5 393 M
-( channel-related messages contain the recipient's channel number for) s
-5 382 M
-( the channel.) s
-5 360 M
-( Channels are flow-controlled. No data may be sent to a channel until) s
-5 349 M
-( a message is received to indicate that window space is available.) s
-5 327 M
-(5.1 Opening a Channel) s
-5 305 M
-( When either side wishes to open a new channel, it allocates a local) s
-5 294 M
-( number for the channel. It then sends the following message to the) s
-5 283 M
-( other side, and includes the local channel number and initial window) s
-5 272 M
-( size in the message.) s
-5 250 M
-( byte SSH_MSG_CHANNEL_OPEN) s
-5 239 M
-( string channel type \(restricted to US-ASCII\)) s
-5 228 M
-( uint32 sender channel) s
-5 217 M
-( uint32 initial window size) s
-5 206 M
-( uint32 maximum packet size) s
-5 195 M
-( ... channel type specific data follows) s
-5 173 M
-( The channel type is a name as described in the SSH architecture) s
-5 129 M
-(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 4]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (4,5) 3
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 5 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Connection Protocol Oct 2003) s
-5 690 M
-( document, with similar extension mechanisms. `sender channel' is a) s
-5 679 M
-( local identifier for the channel used by the sender of this message.) s
-5 668 M
-( `initial window size' specifies how many bytes of channel data can be) s
-5 657 M
-( sent to the sender of this message without adjusting the window.) s
-5 646 M
-( `Maximum packet size' specifies the maximum size of an individual) s
-5 635 M
-( data packet that can be sent to the sender \(for example, one might) s
-5 624 M
-( want to use smaller packets for interactive connections to get better) s
-5 613 M
-( interactive response on slow links\).) s
-5 591 M
-( The remote side then decides whether it can open the channel, and) s
-5 580 M
-( responds with either) s
-5 558 M
-( byte SSH_MSG_CHANNEL_OPEN_CONFIRMATION) s
-5 547 M
-( uint32 recipient channel) s
-5 536 M
-( uint32 sender channel) s
-5 525 M
-( uint32 initial window size) s
-5 514 M
-( uint32 maximum packet size) s
-5 503 M
-( ... channel type specific data follows) s
-5 481 M
-( where `recipient channel' is the channel number given in the original) s
-5 470 M
-( open request, and `sender channel' is the channel number allocated by) s
-5 459 M
-( the other side, or) s
-5 437 M
-( byte SSH_MSG_CHANNEL_OPEN_FAILURE) s
-5 426 M
-( uint32 recipient channel) s
-5 415 M
-( uint32 reason code) s
-5 404 M
-( string additional textual information \(ISO-10646 UTF-8 [RFC2279]\)) s
-5 393 M
-( string language tag \(as defined in [RFC3066]\)) s
-5 371 M
-( If the recipient of the SSH_MSG_CHANNEL_OPEN message does not support) s
-5 360 M
-( the specified channel type, it simply responds with) s
-5 349 M
-( SSH_MSG_CHANNEL_OPEN_FAILURE. The client MAY show the additional) s
-5 338 M
-( information to the user. If this is done, the client software should) s
-5 327 M
-( take the precautions discussed in [SSH-ARCH].) s
-5 305 M
-( The following reason codes are defined:) s
-5 283 M
-( #define SSH_OPEN_ADMINISTRATIVELY_PROHIBITED 1) s
-5 272 M
-( #define SSH_OPEN_CONNECT_FAILED 2) s
-5 261 M
-( #define SSH_OPEN_UNKNOWN_CHANNEL_TYPE 3) s
-5 250 M
-( #define SSH_OPEN_RESOURCE_SHORTAGE 4) s
-5 217 M
-(5.2 Data Transfer) s
-5 195 M
-( The window size specifies how many bytes the other party can send) s
-5 184 M
-( before it must wait for the window to be adjusted. Both parties use) s
-5 173 M
-( the following message to adjust the window.) s
-5 129 M
-(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 5]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 6 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Connection Protocol Oct 2003) s
-5 690 M
-( byte SSH_MSG_CHANNEL_WINDOW_ADJUST) s
-5 679 M
-( uint32 recipient channel) s
-5 668 M
-( uint32 bytes to add) s
-5 646 M
-( After receiving this message, the recipient MAY send the given number) s
-5 635 M
-( of bytes more than it was previously allowed to send; the window size) s
-5 624 M
-( is incremented.) s
-5 602 M
-( Data transfer is done with messages of the following type.) s
-5 580 M
-( byte SSH_MSG_CHANNEL_DATA) s
-5 569 M
-( uint32 recipient channel) s
-5 558 M
-( string data) s
-5 536 M
-( The maximum amount of data allowed is the current window size. The) s
-5 525 M
-( window size is decremented by the amount of data sent. Both parties) s
-5 514 M
-( MAY ignore all extra data sent after the allowed window is empty.) s
-5 492 M
-( Additionally, some channels can transfer several types of data. An) s
-5 481 M
-( example of this is stderr data from interactive sessions. Such data) s
-5 470 M
-( can be passed with SSH_MSG_CHANNEL_EXTENDED_DATA messages, where a) s
-5 459 M
-( separate integer specifies the type of the data. The available types) s
-5 448 M
-( and their interpretation depend on the type of the channel.) s
-5 426 M
-( byte SSH_MSG_CHANNEL_EXTENDED_DATA) s
-5 415 M
-( uint32 recipient_channel) s
-5 404 M
-( uint32 data_type_code) s
-5 393 M
-( string data) s
-5 371 M
-( Data sent with these messages consumes the same window as ordinary) s
-5 360 M
-( data.) s
-5 338 M
-( Currently, only the following type is defined.) s
-5 316 M
-( #define SSH_EXTENDED_DATA_STDERR 1) s
-5 283 M
-(5.3 Closing a Channel) s
-5 261 M
-( When a party will no longer send more data to a channel, it SHOULD) s
-5 250 M
-( send SSH_MSG_CHANNEL_EOF.) s
-5 228 M
-( byte SSH_MSG_CHANNEL_EOF) s
-5 217 M
-( uint32 recipient_channel) s
-5 195 M
-( No explicit response is sent to this message; however, the) s
-5 184 M
-( application may send EOF to whatever is at the other end of the) s
-5 173 M
-( channel. Note that the channel remains open after this message, and) s
-5 129 M
-(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 6]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (6,7) 4
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 7 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Connection Protocol Oct 2003) s
-5 690 M
-( more data may still be sent in the other direction. This message) s
-5 679 M
-( does not consume window space and can be sent even if no window space) s
-5 668 M
-( is available.) s
-5 646 M
-( When either party wishes to terminate the channel, it sends) s
-5 635 M
-( SSH_MSG_CHANNEL_CLOSE. Upon receiving this message, a party MUST) s
-5 624 M
-( send back a SSH_MSG_CHANNEL_CLOSE unless it has already sent this) s
-5 613 M
-( message for the channel. The channel is considered closed for a) s
-5 602 M
-( party when it has both sent and received SSH_MSG_CHANNEL_CLOSE, and) s
-5 591 M
-( the party may then reuse the channel number. A party MAY send) s
-5 580 M
-( SSH_MSG_CHANNEL_CLOSE without having sent or received) s
-5 569 M
-( SSH_MSG_CHANNEL_EOF.) s
-5 547 M
-( byte SSH_MSG_CHANNEL_CLOSE) s
-5 536 M
-( uint32 recipient_channel) s
-5 514 M
-( This message does not consume window space and can be sent even if no) s
-5 503 M
-( window space is available.) s
-5 481 M
-( It is recommended that any data sent before this message is delivered) s
-5 470 M
-( to the actual destination, if possible.) s
-5 448 M
-(5.4 Channel-Specific Requests) s
-5 426 M
-( Many channel types have extensions that are specific to that) s
-5 415 M
-( particular channel type. An example is requesting a pty \(pseudo) s
-5 404 M
-( terminal\) for an interactive session.) s
-5 382 M
-( All channel-specific requests use the following format.) s
-5 360 M
-( byte SSH_MSG_CHANNEL_REQUEST) s
-5 349 M
-( uint32 recipient channel) s
-5 338 M
-( string request type \(restricted to US-ASCII\)) s
-5 327 M
-( boolean want reply) s
-5 316 M
-( ... type-specific data) s
-5 294 M
-( If want reply is FALSE, no response will be sent to the request.) s
-5 283 M
-( Otherwise, the recipient responds with either SSH_MSG_CHANNEL_SUCCESS) s
-5 272 M
-( or SSH_MSG_CHANNEL_FAILURE, or request-specific continuation) s
-5 261 M
-( messages. If the request is not recognized or is not supported for) s
-5 250 M
-( the channel, SSH_MSG_CHANNEL_FAILURE is returned.) s
-5 228 M
-( This message does not consume window space and can be sent even if no) s
-5 217 M
-( window space is available. Request types are local to each channel) s
-5 206 M
-( type.) s
-5 184 M
-( The client is allowed to send further messages without waiting for) s
-5 173 M
-( the response to the request.) s
-5 129 M
-(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 7]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 8 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Connection Protocol Oct 2003) s
-5 690 M
-( request type names follow the DNS extensibility naming convention) s
-5 679 M
-( outlined in [SSH-ARCH]) s
-5 657 M
-( byte SSH_MSG_CHANNEL_SUCCESS) s
-5 646 M
-( uint32 recipient_channel) s
-5 613 M
-( byte SSH_MSG_CHANNEL_FAILURE) s
-5 602 M
-( uint32 recipient_channel) s
-5 580 M
-( These messages do not consume window space and can be sent even if no) s
-5 569 M
-( window space is available.) s
-5 547 M
-(6. Interactive Sessions) s
-5 525 M
-( A session is a remote execution of a program. The program may be a) s
-5 514 M
-( shell, an application, a system command, or some built-in subsystem.) s
-5 503 M
-( It may or may not have a tty, and may or may not involve X11) s
-5 492 M
-( forwarding. Multiple sessions can be active simultaneously.) s
-5 470 M
-(6.1 Opening a Session) s
-5 448 M
-( A session is started by sending the following message.) s
-5 426 M
-( byte SSH_MSG_CHANNEL_OPEN) s
-5 415 M
-( string "session") s
-5 404 M
-( uint32 sender channel) s
-5 393 M
-( uint32 initial window size) s
-5 382 M
-( uint32 maximum packet size) s
-5 360 M
-( Client implementations SHOULD reject any session channel open) s
-5 349 M
-( requests to make it more difficult for a corrupt server to attack the) s
-5 338 M
-( client.) s
-5 316 M
-(6.2 Requesting a Pseudo-Terminal) s
-5 294 M
-( A pseudo-terminal can be allocated for the session by sending the) s
-5 283 M
-( following message.) s
-5 261 M
-( byte SSH_MSG_CHANNEL_REQUEST) s
-5 250 M
-( uint32 recipient_channel) s
-5 239 M
-( string "pty-req") s
-5 228 M
-( boolean want_reply) s
-5 217 M
-( string TERM environment variable value \(e.g., vt100\)) s
-5 206 M
-( uint32 terminal width, characters \(e.g., 80\)) s
-5 195 M
-( uint32 terminal height, rows \(e.g., 24\)) s
-5 184 M
-( uint32 terminal width, pixels \(e.g., 640\)) s
-5 173 M
-( uint32 terminal height, pixels \(e.g., 480\)) s
-5 129 M
-(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 8]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (8,9) 5
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 9 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Connection Protocol Oct 2003) s
-5 690 M
-( string encoded terminal modes) s
-5 668 M
-( The encoding of terminal modes is described in Section Encoding of) s
-5 657 M
-( Terminal Modes \(Section 8\). Zero dimension parameters MUST be) s
-5 646 M
-( ignored. The character/row dimensions override the pixel dimensions) s
-5 635 M
-( \(when nonzero\). Pixel dimensions refer to the drawable area of the) s
-5 624 M
-( window.) s
-5 602 M
-( The dimension parameters are only informational.) s
-5 580 M
-( The client SHOULD ignore pty requests.) s
-5 558 M
-(6.3 X11 Forwarding) s
-5 536 M
-(6.3.1 Requesting X11 Forwarding) s
-5 514 M
-( X11 forwarding may be requested for a session by sending) s
-5 492 M
-( byte SSH_MSG_CHANNEL_REQUEST) s
-5 481 M
-( uint32 recipient channel) s
-5 470 M
-( string "x11-req") s
-5 459 M
-( boolean want reply) s
-5 448 M
-( boolean single connection) s
-5 437 M
-( string x11 authentication protocol) s
-5 426 M
-( string x11 authentication cookie) s
-5 415 M
-( uint32 x11 screen number) s
-5 393 M
-( It is recommended that the authentication cookie that is sent be a) s
-5 382 M
-( fake, random cookie, and that the cookie is checked and replaced by) s
-5 371 M
-( the real cookie when a connection request is received.) s
-5 349 M
-( X11 connection forwarding should stop when the session channel is) s
-5 338 M
-( closed; however, already opened forwardings should not be) s
-5 327 M
-( automatically closed when the session channel is closed.) s
-5 305 M
-( If `single connection' is TRUE, only a single connection should be) s
-5 294 M
-( forwarded. No more connections will be forwarded after the first, or) s
-5 283 M
-( after the session channel has been closed.) s
-5 261 M
-( The "x11 authentication protocol" is the name of the X11) s
-5 250 M
-( authentication method used, e.g. "MIT-MAGIC-COOKIE-1".) s
-5 228 M
-( The x11 authentication cookie MUST be hexadecimal encoded.) s
-5 206 M
-( X Protocol is documented in [SCHEIFLER].) s
-5 129 M
-(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 9]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 10 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Connection Protocol Oct 2003) s
-5 690 M
-(6.3.2 X11 Channels) s
-5 668 M
-( X11 channels are opened with a channel open request. The resulting) s
-5 657 M
-( channels are independent of the session, and closing the session) s
-5 646 M
-( channel does not close the forwarded X11 channels.) s
-5 624 M
-( byte SSH_MSG_CHANNEL_OPEN) s
-5 613 M
-( string "x11") s
-5 602 M
-( uint32 sender channel) s
-5 591 M
-( uint32 initial window size) s
-5 580 M
-( uint32 maximum packet size) s
-5 569 M
-( string originator address \(e.g. "192.168.7.38"\)) s
-5 558 M
-( uint32 originator port) s
-5 536 M
-( The recipient should respond with SSH_MSG_CHANNEL_OPEN_CONFIRMATION) s
-5 525 M
-( or SSH_MSG_CHANNEL_OPEN_FAILURE.) s
-5 503 M
-( Implementations MUST reject any X11 channel open requests if they) s
-5 492 M
-( have not requested X11 forwarding.) s
-5 470 M
-(6.4 Environment Variable Passing) s
-5 448 M
-( Environment variables may be passed to the shell/command to be) s
-5 437 M
-( started later. Uncontrolled setting of environment variables in a) s
-5 426 M
-( privileged process can be a security hazard. It is recommended that) s
-5 415 M
-( implementations either maintain a list of allowable variable names or) s
-5 404 M
-( only set environment variables after the server process has dropped) s
-5 393 M
-( sufficient privileges.) s
-5 371 M
-( byte SSH_MSG_CHANNEL_REQUEST) s
-5 360 M
-( uint32 recipient channel) s
-5 349 M
-( string "env") s
-5 338 M
-( boolean want reply) s
-5 327 M
-( string variable name) s
-5 316 M
-( string variable value) s
-5 283 M
-(6.5 Starting a Shell or a Command) s
-5 261 M
-( Once the session has been set up, a program is started at the remote) s
-5 250 M
-( end. The program can be a shell, an application program or a) s
-5 239 M
-( subsystem with a host-independent name. Only one of these requests) s
-5 228 M
-( can succeed per channel.) s
-5 206 M
-( byte SSH_MSG_CHANNEL_REQUEST) s
-5 195 M
-( uint32 recipient channel) s
-5 184 M
-( string "shell") s
-5 173 M
-( boolean want reply) s
-5 129 M
-(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 10]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (10,11) 6
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 11 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Connection Protocol Oct 2003) s
-5 690 M
-( This message will request the user's default shell \(typically defined) s
-5 679 M
-( in /etc/passwd in UNIX systems\) to be started at the other end.) s
-5 657 M
-( byte SSH_MSG_CHANNEL_REQUEST) s
-5 646 M
-( uint32 recipient channel) s
-5 635 M
-( string "exec") s
-5 624 M
-( boolean want reply) s
-5 613 M
-( string command) s
-5 591 M
-( This message will request the server to start the execution of the) s
-5 580 M
-( given command. The command string may contain a path. Normal) s
-5 569 M
-( precautions MUST be taken to prevent the execution of unauthorized) s
-5 558 M
-( commands.) s
-5 536 M
-( byte SSH_MSG_CHANNEL_REQUEST) s
-5 525 M
-( uint32 recipient channel) s
-5 514 M
-( string "subsystem") s
-5 503 M
-( boolean want reply) s
-5 492 M
-( string subsystem name) s
-5 470 M
-( This last form executes a predefined subsystem. It is expected that) s
-5 459 M
-( these will include a general file transfer mechanism, and possibly) s
-5 448 M
-( other features. Implementations may also allow configuring more such) s
-5 437 M
-( mechanisms. As the user's shell is usually used to execute the) s
-5 426 M
-( subsystem, it is advisable for the subsystem protocol to have a) s
-5 415 M
-( "magic cookie" at the beginning of the protocol transaction to) s
-5 404 M
-( distinguish it from arbitrary output generated by shell) s
-5 393 M
-( initialization scripts etc. This spurious output from the shell may) s
-5 382 M
-( be filtered out either at the server or at the client.) s
-5 360 M
-( The server SHOULD not halt the execution of the protocol stack when) s
-5 349 M
-( starting a shell or a program. All input and output from these SHOULD) s
-5 338 M
-( be redirected to the channel or to the encrypted tunnel.) s
-5 316 M
-( It is RECOMMENDED to request and check the reply for these messages.) s
-5 305 M
-( The client SHOULD ignore these messages.) s
-5 283 M
-( Subsystem names follow the DNS extensibility naming convention) s
-5 272 M
-( outlined in [SSH-ARCH].) s
-5 250 M
-(6.6 Session Data Transfer) s
-5 228 M
-( Data transfer for a session is done using SSH_MSG_CHANNEL_DATA and) s
-5 217 M
-( SSH_MSG_CHANNEL_EXTENDED_DATA packets and the window mechanism. The) s
-5 206 M
-( extended data type SSH_EXTENDED_DATA_STDERR has been defined for) s
-5 195 M
-( stderr data.) s
-5 129 M
-(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 11]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 12 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Connection Protocol Oct 2003) s
-5 690 M
-(6.7 Window Dimension Change Message) s
-5 668 M
-( When the window \(terminal\) size changes on the client side, it MAY) s
-5 657 M
-( send a message to the other side to inform it of the new dimensions.) s
-5 635 M
-( byte SSH_MSG_CHANNEL_REQUEST) s
-5 624 M
-( uint32 recipient_channel) s
-5 613 M
-( string "window-change") s
-5 602 M
-( boolean FALSE) s
-5 591 M
-( uint32 terminal width, columns) s
-5 580 M
-( uint32 terminal height, rows) s
-5 569 M
-( uint32 terminal width, pixels) s
-5 558 M
-( uint32 terminal height, pixels) s
-5 536 M
-( No response SHOULD be sent to this message.) s
-5 514 M
-(6.8 Local Flow Control) s
-5 492 M
-( On many systems, it is possible to determine if a pseudo-terminal is) s
-5 481 M
-( using control-S/control-Q flow control. When flow control is) s
-5 470 M
-( allowed, it is often desirable to do the flow control at the client) s
-5 459 M
-( end to speed up responses to user requests. This is facilitated by) s
-5 448 M
-( the following notification. Initially, the server is responsible for) s
-5 437 M
-( flow control. \(Here, again, client means the side originating the) s
-5 426 M
-( session, and server means the other side.\)) s
-5 404 M
-( The message below is used by the server to inform the client when it) s
-5 393 M
-( can or cannot perform flow control \(control-S/control-Q processing\).) s
-5 382 M
-( If `client can do' is TRUE, the client is allowed to do flow control) s
-5 371 M
-( using control-S and control-Q. The client MAY ignore this message.) s
-5 349 M
-( byte SSH_MSG_CHANNEL_REQUEST) s
-5 338 M
-( uint32 recipient channel) s
-5 327 M
-( string "xon-xoff") s
-5 316 M
-( boolean FALSE) s
-5 305 M
-( boolean client can do) s
-5 283 M
-( No response is sent to this message.) s
-5 261 M
-(6.9 Signals) s
-5 239 M
-( A signal can be delivered to the remote process/service using the) s
-5 228 M
-( following message. Some systems may not implement signals, in which) s
-5 217 M
-( case they SHOULD ignore this message.) s
-5 195 M
-( byte SSH_MSG_CHANNEL_REQUEST) s
-5 184 M
-( uint32 recipient channel) s
-5 173 M
-( string "signal") s
-5 129 M
-(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 12]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (12,13) 7
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 13 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Connection Protocol Oct 2003) s
-5 690 M
-( boolean FALSE) s
-5 679 M
-( string signal name without the "SIG" prefix.) s
-5 657 M
-( Signal names will be encoded as discussed in the "exit-signal") s
-5 646 M
-( SSH_MSG_CHANNEL_REQUEST.) s
-5 624 M
-(6.10 Returning Exit Status) s
-5 602 M
-( When the command running at the other end terminates, the following) s
-5 591 M
-( message can be sent to return the exit status of the command.) s
-5 580 M
-( Returning the status is RECOMMENDED. No acknowledgment is sent for) s
-5 569 M
-( this message. The channel needs to be closed with) s
-5 558 M
-( SSH_MSG_CHANNEL_CLOSE after this message.) s
-5 536 M
-( The client MAY ignore these messages.) s
-5 514 M
-( byte SSH_MSG_CHANNEL_REQUEST) s
-5 503 M
-( uint32 recipient_channel) s
-5 492 M
-( string "exit-status") s
-5 481 M
-( boolean FALSE) s
-5 470 M
-( uint32 exit_status) s
-5 448 M
-( The remote command may also terminate violently due to a signal.) s
-5 437 M
-( Such a condition can be indicated by the following message. A zero) s
-5 426 M
-( exit_status usually means that the command terminated successfully.) s
-5 404 M
-( byte SSH_MSG_CHANNEL_REQUEST) s
-5 393 M
-( uint32 recipient channel) s
-5 382 M
-( string "exit-signal") s
-5 371 M
-( boolean FALSE) s
-5 360 M
-( string signal name without the "SIG" prefix.) s
-5 349 M
-( boolean core dumped) s
-5 338 M
-( string error message \(ISO-10646 UTF-8\)) s
-5 327 M
-( string language tag \(as defined in [RFC3066]\)) s
-5 305 M
-( The signal name is one of the following \(these are from [POSIX]\)) s
-5 283 M
-( ABRT) s
-5 272 M
-( ALRM) s
-5 261 M
-( FPE) s
-5 250 M
-( HUP) s
-5 239 M
-( ILL) s
-5 228 M
-( INT) s
-5 217 M
-( KILL) s
-5 206 M
-( PIPE) s
-5 195 M
-( QUIT) s
-5 184 M
-( SEGV) s
-5 173 M
-( TERM) s
-5 129 M
-(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 13]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 14 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Connection Protocol Oct 2003) s
-5 690 M
-( USR1) s
-5 679 M
-( USR2) s
-5 657 M
-( Additional signal names MAY be sent in the format "sig-name@xyz",) s
-5 646 M
-( where `sig-name' and `xyz' may be anything a particular implementor) s
-5 635 M
-( wants \(except the `@' sign\). However, it is suggested that if a) s
-5 624 M
-( `configure' script is used, the non-standard signal names it finds be) s
-5 613 M
-( encoded as "[email protected]", where `SIG' is the signal name) s
-5 602 M
-( without the "SIG" prefix, and `xyz' be the host type, as determined) s
-5 591 M
-( by `config.guess'.) s
-5 569 M
-( The `error message' contains an additional explanation of the error) s
-5 558 M
-( message. The message may consist of multiple lines. The client) s
-5 547 M
-( software MAY display this message to the user. If this is done, the) s
-5 536 M
-( client software should take the precautions discussed in [SSH-ARCH].) s
-5 514 M
-(7. TCP/IP Port Forwarding) s
-5 492 M
-(7.1 Requesting Port Forwarding) s
-5 470 M
-( A party need not explicitly request forwardings from its own end to) s
-5 459 M
-( the other direction. However, if it wishes that connections to a) s
-5 448 M
-( port on the other side be forwarded to the local side, it must) s
-5 437 M
-( explicitly request this.) s
-5 404 M
-( byte SSH_MSG_GLOBAL_REQUEST) s
-5 393 M
-( string "tcpip-forward") s
-5 382 M
-( boolean want reply) s
-5 371 M
-( string address to bind \(e.g. "0.0.0.0"\)) s
-5 360 M
-( uint32 port number to bind) s
-5 338 M
-( `Address to bind' and `port number to bind' specify the IP address) s
-5 327 M
-( and port to which the socket to be listened is bound. The address) s
-5 316 M
-( should be "0.0.0.0" if connections are allowed from anywhere. \(Note) s
-5 305 M
-( that the client can still filter connections based on information) s
-5 294 M
-( passed in the open request.\)) s
-5 272 M
-( Implementations should only allow forwarding privileged ports if the) s
-5 261 M
-( user has been authenticated as a privileged user.) s
-5 239 M
-( Client implementations SHOULD reject these messages; they are) s
-5 228 M
-( normally only sent by the client.) s
-5 195 M
-( If a client passes 0 as port number to bind and has want reply TRUE) s
-5 184 M
-( then the server allocates the next available unprivileged port number) s
-5 173 M
-( and replies with the following message, otherwise there is no) s
-5 129 M
-(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 14]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (14,15) 8
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 15 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Connection Protocol Oct 2003) s
-5 690 M
-( response specific data.) s
-5 657 M
-( byte SSH_MSG_GLOBAL_REQUEST_SUCCESS) s
-5 646 M
-( uint32 port that was bound on the server) s
-5 624 M
-( A port forwarding can be cancelled with the following message. Note) s
-5 613 M
-( that channel open requests may be received until a reply to this) s
-5 602 M
-( message is received.) s
-5 580 M
-( byte SSH_MSG_GLOBAL_REQUEST) s
-5 569 M
-( string "cancel-tcpip-forward") s
-5 558 M
-( boolean want reply) s
-5 547 M
-( string address_to_bind \(e.g. "127.0.0.1"\)) s
-5 536 M
-( uint32 port number to bind) s
-5 514 M
-( Client implementations SHOULD reject these messages; they are) s
-5 503 M
-( normally only sent by the client.) s
-5 481 M
-(7.2 TCP/IP Forwarding Channels) s
-5 459 M
-( When a connection comes to a port for which remote forwarding has) s
-5 448 M
-( been requested, a channel is opened to forward the port to the other) s
-5 437 M
-( side.) s
-5 415 M
-( byte SSH_MSG_CHANNEL_OPEN) s
-5 404 M
-( string "forwarded-tcpip") s
-5 393 M
-( uint32 sender channel) s
-5 382 M
-( uint32 initial window size) s
-5 371 M
-( uint32 maximum packet size) s
-5 360 M
-( string address that was connected) s
-5 349 M
-( uint32 port that was connected) s
-5 338 M
-( string originator IP address) s
-5 327 M
-( uint32 originator port) s
-5 305 M
-( Implementations MUST reject these messages unless they have) s
-5 294 M
-( previously requested a remote TCP/IP port forwarding with the given) s
-5 283 M
-( port number.) s
-5 261 M
-( When a connection comes to a locally forwarded TCP/IP port, the) s
-5 250 M
-( following packet is sent to the other side. Note that these messages) s
-5 239 M
-( MAY be sent also for ports for which no forwarding has been) s
-5 228 M
-( explicitly requested. The receiving side must decide whether to) s
-5 217 M
-( allow the forwarding.) s
-5 195 M
-( byte SSH_MSG_CHANNEL_OPEN) s
-5 184 M
-( string "direct-tcpip") s
-5 173 M
-( uint32 sender channel) s
-5 129 M
-(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 15]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 16 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Connection Protocol Oct 2003) s
-5 690 M
-( uint32 initial window size) s
-5 679 M
-( uint32 maximum packet size) s
-5 668 M
-( string host to connect) s
-5 657 M
-( uint32 port to connect) s
-5 646 M
-( string originator IP address) s
-5 635 M
-( uint32 originator port) s
-5 613 M
-( `Host to connect' and `port to connect' specify the TCP/IP host and) s
-5 602 M
-( port where the recipient should connect the channel. `Host to) s
-5 591 M
-( connect' may be either a domain name or a numeric IP address.) s
-5 569 M
-( `Originator IP address' is the numeric IP address of the machine) s
-5 558 M
-( where the connection request comes from, and `originator port' is the) s
-5 547 M
-( port on the originator host from where the connection came from.) s
-5 525 M
-( Forwarded TCP/IP channels are independent of any sessions, and) s
-5 514 M
-( closing a session channel does not in any way imply that forwarded) s
-5 503 M
-( connections should be closed.) s
-5 481 M
-( Client implementations SHOULD reject direct TCP/IP open requests for) s
-5 470 M
-( security reasons.) s
-5 448 M
-(8. Encoding of Terminal Modes) s
-5 426 M
-( Terminal modes \(as passed in a pty request\) are encoded into a byte) s
-5 415 M
-( stream. It is intended that the coding be portable across different) s
-5 404 M
-( environments.) s
-5 382 M
-( The tty mode description is a stream of bytes. The stream consists) s
-5 371 M
-( of opcode-argument pairs. It is terminated by opcode TTY_OP_END \(0\).) s
-5 360 M
-( Opcodes 1 to 159 have a single uint32 argument. Opcodes 160 to 255) s
-5 349 M
-( are not yet defined, and cause parsing to stop \(they should only be) s
-5 338 M
-( used after any other data\).) s
-5 316 M
-( The client SHOULD put in the stream any modes it knows about, and the) s
-5 305 M
-( server MAY ignore any modes it does not know about. This allows some) s
-5 294 M
-( degree of machine-independence, at least between systems that use a) s
-5 283 M
-( POSIX-like tty interface. The protocol can support other systems as) s
-5 272 M
-( well, but the client may need to fill reasonable values for a number) s
-5 261 M
-( of parameters so the server pty gets set to a reasonable mode \(the) s
-5 250 M
-( server leaves all unspecified mode bits in their default values, and) s
-5 239 M
-( only some combinations make sense\).) s
-5 217 M
-( The following opcodes have been defined. The naming of opcodes) s
-5 206 M
-( mostly follows the POSIX terminal mode flags.) s
-5 184 M
-( 0 TTY_OP_END Indicates end of options.) s
-5 173 M
-( 1 VINTR Interrupt character; 255 if none. Similarly for the) s
-5 129 M
-(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 16]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (16,17) 9
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 17 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Connection Protocol Oct 2003) s
-5 690 M
-( other characters. Not all of these characters are) s
-5 679 M
-( supported on all systems.) s
-5 668 M
-( 2 VQUIT The quit character \(sends SIGQUIT signal on POSIX) s
-5 657 M
-( systems\).) s
-5 646 M
-( 3 VERASE Erase the character to left of the cursor.) s
-5 635 M
-( 4 VKILL Kill the current input line.) s
-5 624 M
-( 5 VEOF End-of-file character \(sends EOF from the terminal\).) s
-5 613 M
-( 6 VEOL End-of-line character in addition to carriage return) s
-5 602 M
-( and/or linefeed.) s
-5 591 M
-( 7 VEOL2 Additional end-of-line character.) s
-5 580 M
-( 8 VSTART Continues paused output \(normally control-Q\).) s
-5 569 M
-( 9 VSTOP Pauses output \(normally control-S\).) s
-5 558 M
-( 10 VSUSP Suspends the current program.) s
-5 547 M
-( 11 VDSUSP Another suspend character.) s
-5 536 M
-( 12 VREPRINT Reprints the current input line.) s
-5 525 M
-( 13 VWERASE Erases a word left of cursor.) s
-5 514 M
-( 14 VLNEXT Enter the next character typed literally, even if it) s
-5 503 M
-( is a special character) s
-5 492 M
-( 15 VFLUSH Character to flush output.) s
-5 481 M
-( 16 VSWTCH Switch to a different shell layer.) s
-5 470 M
-( 17 VSTATUS Prints system status line \(load, command, pid etc\).) s
-5 459 M
-( 18 VDISCARD Toggles the flushing of terminal output.) s
-5 448 M
-( 30 IGNPAR The ignore parity flag. The parameter SHOULD be 0 if) s
-5 437 M
-( this flag is FALSE set, and 1 if it is TRUE.) s
-5 426 M
-( 31 PARMRK Mark parity and framing errors.) s
-5 415 M
-( 32 INPCK Enable checking of parity errors.) s
-5 404 M
-( 33 ISTRIP Strip 8th bit off characters.) s
-5 393 M
-( 34 INLCR Map NL into CR on input.) s
-5 382 M
-( 35 IGNCR Ignore CR on input.) s
-5 371 M
-( 36 ICRNL Map CR to NL on input.) s
-5 360 M
-( 37 IUCLC Translate uppercase characters to lowercase.) s
-5 349 M
-( 38 IXON Enable output flow control.) s
-5 338 M
-( 39 IXANY Any char will restart after stop.) s
-5 327 M
-( 40 IXOFF Enable input flow control.) s
-5 316 M
-( 41 IMAXBEL Ring bell on input queue full.) s
-5 305 M
-( 50 ISIG Enable signals INTR, QUIT, [D]SUSP.) s
-5 294 M
-( 51 ICANON Canonicalize input lines.) s
-5 283 M
-( 52 XCASE Enable input and output of uppercase characters by) s
-5 272 M
-( preceding their lowercase equivalents with `\\'.) s
-5 261 M
-( 53 ECHO Enable echoing.) s
-5 250 M
-( 54 ECHOE Visually erase chars.) s
-5 239 M
-( 55 ECHOK Kill character discards current line.) s
-5 228 M
-( 56 ECHONL Echo NL even if ECHO is off.) s
-5 217 M
-( 57 NOFLSH Don't flush after interrupt.) s
-5 206 M
-( 58 TOSTOP Stop background jobs from output.) s
-5 195 M
-( 59 IEXTEN Enable extensions.) s
-5 184 M
-( 60 ECHOCTL Echo control characters as ^\(Char\).) s
-5 173 M
-( 61 ECHOKE Visual erase for line kill.) s
-5 129 M
-(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 17]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 18 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Connection Protocol Oct 2003) s
-5 690 M
-( 62 PENDIN Retype pending input.) s
-5 679 M
-( 70 OPOST Enable output processing.) s
-5 668 M
-( 71 OLCUC Convert lowercase to uppercase.) s
-5 657 M
-( 72 ONLCR Map NL to CR-NL.) s
-5 646 M
-( 73 OCRNL Translate carriage return to newline \(output\).) s
-5 635 M
-( 74 ONOCR Translate newline to carriage return-newline) s
-5 624 M
-( \(output\).) s
-5 613 M
-( 75 ONLRET Newline performs a carriage return \(output\).) s
-5 602 M
-( 90 CS7 7 bit mode.) s
-5 591 M
-( 91 CS8 8 bit mode.) s
-5 580 M
-( 92 PARENB Parity enable.) s
-5 569 M
-( 93 PARODD Odd parity, else even.) s
-5 547 M
-( 128 TTY_OP_ISPEED Specifies the input baud rate in bits per second.) s
-5 536 M
-( 129 TTY_OP_OSPEED Specifies the output baud rate in bits per second.) s
-5 503 M
-(9. Summary of Message Numbers) s
-5 481 M
-( #define SSH_MSG_GLOBAL_REQUEST 80) s
-5 470 M
-( #define SSH_MSG_REQUEST_SUCCESS 81) s
-5 459 M
-( #define SSH_MSG_REQUEST_FAILURE 82) s
-5 448 M
-( #define SSH_MSG_CHANNEL_OPEN 90) s
-5 437 M
-( #define SSH_MSG_CHANNEL_OPEN_CONFIRMATION 91) s
-5 426 M
-( #define SSH_MSG_CHANNEL_OPEN_FAILURE 92) s
-5 415 M
-( #define SSH_MSG_CHANNEL_WINDOW_ADJUST 93) s
-5 404 M
-( #define SSH_MSG_CHANNEL_DATA 94) s
-5 393 M
-( #define SSH_MSG_CHANNEL_EXTENDED_DATA 95) s
-5 382 M
-( #define SSH_MSG_CHANNEL_EOF 96) s
-5 371 M
-( #define SSH_MSG_CHANNEL_CLOSE 97) s
-5 360 M
-( #define SSH_MSG_CHANNEL_REQUEST 98) s
-5 349 M
-( #define SSH_MSG_CHANNEL_SUCCESS 99) s
-5 338 M
-( #define SSH_MSG_CHANNEL_FAILURE 100) s
-5 305 M
-(10. Security Considerations) s
-5 283 M
-( This protocol is assumed to run on top of a secure, authenticated) s
-5 272 M
-( transport. User authentication and protection against network-level) s
-5 261 M
-( attacks are assumed to be provided by the underlying protocols.) s
-5 239 M
-( It is RECOMMENDED that implementations disable all the potentially) s
-5 228 M
-( dangerous features \(e.g. agent forwarding, X11 forwarding, and TCP/IP) s
-5 217 M
-( forwarding\) if the host key has changed.) s
-5 195 M
-( Full security considerations for this protocol are provided in) s
-5 184 M
-( Section 8 of [SSH-ARCH]) s
-5 129 M
-(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 18]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (18,19) 10
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 19 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Connection Protocol Oct 2003) s
-5 690 M
-(11. iana cONSiderations) s
-5 668 M
-( This document is part of a set, the IANA considerations for the SSH) s
-5 657 M
-( protocol as defined in [SSH-ARCH], [SSH-TRANS], [SSH-USERAUTH],) s
-5 646 M
-( [SSH-CONNECT] are detailed in [SSH-NUMBERS].) s
-5 624 M
-(12. Intellectual Property) s
-5 602 M
-( The IETF takes no position regarding the validity or scope of any) s
-5 591 M
-( intellectual property or other rights that might be claimed to) s
-5 580 M
-( pertain to the implementation or use of the technology described in) s
-5 569 M
-( this document or the extent to which any license under such rights) s
-5 558 M
-( might or might not be available; neither does it represent that it) s
-5 547 M
-( has made any effort to identify any such rights. Information on the) s
-5 536 M
-( IETF's procedures with respect to rights in standards-track and) s
-5 525 M
-( standards-related documentation can be found in BCP-11. Copies of) s
-5 514 M
-( claims of rights made available for publication and any assurances of) s
-5 503 M
-( licenses to be made available, or the result of an attempt made to) s
-5 492 M
-( obtain a general license or permission for the use of such) s
-5 481 M
-( proprietary rights by implementers or users of this specification can) s
-5 470 M
-( be obtained from the IETF Secretariat.) s
-5 448 M
-( The IETF has been notified of intellectual property rights claimed in) s
-5 437 M
-( regard to some or all of the specification contained in this) s
-5 426 M
-( document. For more information consult the online list of claimed) s
-5 415 M
-( rights.) s
-5 393 M
-(Normative References) s
-5 371 M
-( [SSH-ARCH]) s
-5 360 M
-( Ylonen, T., "SSH Protocol Architecture", I-D) s
-5 349 M
-( draft-ietf-architecture-15.txt, Oct 2003.) s
-5 327 M
-( [SSH-TRANS]) s
-5 316 M
-( Ylonen, T., "SSH Transport Layer Protocol", I-D) s
-5 305 M
-( draft-ietf-transport-17.txt, Oct 2003.) s
-5 283 M
-( [SSH-USERAUTH]) s
-5 272 M
-( Ylonen, T., "SSH Authentication Protocol", I-D) s
-5 261 M
-( draft-ietf-userauth-18.txt, Oct 2003.) s
-5 239 M
-( [SSH-CONNECT]) s
-5 228 M
-( Ylonen, T., "SSH Connection Protocol", I-D) s
-5 217 M
-( draft-ietf-connect-18.txt, Oct 2003.) s
-5 195 M
-( [SSH-NUMBERS]) s
-5 184 M
-( Lehtinen, S. and D. Moffat, "SSH Protocol Assigned) s
-5 173 M
-( Numbers", I-D draft-ietf-secsh-assignednumbers-05.txt, Oct) s
-5 129 M
-(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 19]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 20 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Connection Protocol Oct 2003) s
-5 690 M
-( 2003.) s
-5 668 M
-( [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate) s
-5 657 M
-( Requirement Levels", BCP 14, RFC 2119, March 1997.) s
-5 635 M
-(Informative References) s
-5 613 M
-( [RFC3066] Alvestrand, H., "Tags for the Identification of) s
-5 602 M
-( Languages", BCP 47, RFC 3066, January 2001.) s
-5 580 M
-( [RFC1884] Hinden, R. and S. Deering, "IP Version 6 Addressing) s
-5 569 M
-( Architecture", RFC 1884, December 1995.) s
-5 547 M
-( [RFC2279] Yergeau, F., "UTF-8, a transformation format of ISO) s
-5 536 M
-( 10646", RFC 2279, January 1998.) s
-5 514 M
-( [SCHEIFLER]) s
-5 503 M
-( Scheifler, R., "X Window System : The Complete Reference) s
-5 492 M
-( to Xlib, X Protocol, Icccm, Xlfd, 3rd edition.", Digital) s
-5 481 M
-( Press ISBN 1555580882, Feburary 1992.) s
-5 459 M
-( [POSIX] ISO/IEC, 9945-1., "Information technology -- Portable) s
-5 448 M
-( Operating System Interface \(POSIX\)-Part 1: System) s
-5 437 M
-( Application Program Interface \(API\) C Language", ANSI/IEE) s
-5 426 M
-( Std 1003.1, July 1996.) s
-5 393 M
-(Authors' Addresses) s
-5 371 M
-( Tatu Ylonen) s
-5 360 M
-( SSH Communications Security Corp) s
-5 349 M
-( Fredrikinkatu 42) s
-5 338 M
-( HELSINKI FIN-00100) s
-5 327 M
-( Finland) s
-5 305 M
-( EMail: [email protected]) s
-5 272 M
-( Darren J. Moffat \(editor\)) s
-5 261 M
-( Sun Microsystems, Inc) s
-5 250 M
-( 17 Network Circle) s
-5 239 M
-( Menlo Park CA 94025) s
-5 228 M
-( USA) s
-5 206 M
-( EMail: [email protected]) s
-5 129 M
-(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 20]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (20,21) 11
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 21 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Connection Protocol Oct 2003) s
-5 690 M
-(Intellectual Property Statement) s
-5 668 M
-( The IETF takes no position regarding the validity or scope of any) s
-5 657 M
-( intellectual property or other rights that might be claimed to) s
-5 646 M
-( pertain to the implementation or use of the technology described in) s
-5 635 M
-( this document or the extent to which any license under such rights) s
-5 624 M
-( might or might not be available; neither does it represent that it) s
-5 613 M
-( has made any effort to identify any such rights. Information on the) s
-5 602 M
-( IETF's procedures with respect to rights in standards-track and) s
-5 591 M
-( standards-related documentation can be found in BCP-11. Copies of) s
-5 580 M
-( claims of rights made available for publication and any assurances of) s
-5 569 M
-( licenses to be made available, or the result of an attempt made to) s
-5 558 M
-( obtain a general license or permission for the use of such) s
-5 547 M
-( proprietary rights by implementors or users of this specification can) s
-5 536 M
-( be obtained from the IETF Secretariat.) s
-5 514 M
-( The IETF invites any interested party to bring to its attention any) s
-5 503 M
-( copyrights, patents or patent applications, or other proprietary) s
-5 492 M
-( rights which may cover technology that may be required to practice) s
-5 481 M
-( this standard. Please address the information to the IETF Executive) s
-5 470 M
-( Director.) s
-5 448 M
-( The IETF has been notified of intellectual property rights claimed in) s
-5 437 M
-( regard to some or all of the specification contained in this) s
-5 426 M
-( document. For more information consult the online list of claimed) s
-5 415 M
-( rights.) s
-5 382 M
-(Full Copyright Statement) s
-5 360 M
-( Copyright \(C\) The Internet Society \(2003\). All Rights Reserved.) s
-5 338 M
-( This document and translations of it may be copied and furnished to) s
-5 327 M
-( others, and derivative works that comment on or otherwise explain it) s
-5 316 M
-( or assist in its implementation may be prepared, copied, published) s
-5 305 M
-( and distributed, in whole or in part, without restriction of any) s
-5 294 M
-( kind, provided that the above copyright notice and this paragraph are) s
-5 283 M
-( included on all such copies and derivative works. However, this) s
-5 272 M
-( document itself may not be modified in any way, such as by removing) s
-5 261 M
-( the copyright notice or references to the Internet Society or other) s
-5 250 M
-( Internet organizations, except as needed for the purpose of) s
-5 239 M
-( developing Internet standards in which case the procedures for) s
-5 228 M
-( copyrights defined in the Internet Standards process must be) s
-5 217 M
-( followed, or as required to translate it into languages other than) s
-5 206 M
-( English.) s
-5 184 M
-( The limited permissions granted above are perpetual and will not be) s
-5 173 M
-( revoked by the Internet Society or its successors or assignees.) s
-5 129 M
-(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 21]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 22 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Connection Protocol Oct 2003) s
-5 690 M
-( This document and the information contained herein is provided on an) s
-5 679 M
-( "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING) s
-5 668 M
-( TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING) s
-5 657 M
-( BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION) s
-5 646 M
-( HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF) s
-5 635 M
-( MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.) s
-5 602 M
-(Acknowledgment) s
-5 580 M
-( Funding for the RFC Editor function is currently provided by the) s
-5 569 M
-( Internet Society.) s
-5 129 M
-(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 22]) s
-_R
-S
-PStoPSsaved restore
-%%Trailer
-%%Pages: 22
-%%DocumentNeededResources: font Courier-Bold Courier
-%%EOF
diff --git a/lib/ssh/doc/standard/draft-ietf-secsh-connect-18.txt b/lib/ssh/doc/standard/draft-ietf-secsh-connect-18.txt
deleted file mode 100644
index 1cb8ad6409..0000000000
--- a/lib/ssh/doc/standard/draft-ietf-secsh-connect-18.txt
+++ /dev/null
@@ -1,1232 +0,0 @@
-
-
-
-Network Working Group T. Ylonen
-Internet-Draft SSH Communications Security Corp
-Expires: March 31, 2004 D. Moffat, Editor, Ed.
- Sun Microsystems, Inc
- Oct 2003
-
-
- SSH Connection Protocol
- draft-ietf-secsh-connect-18.txt
-
-Status of this Memo
-
- This document is an Internet-Draft and is in full conformance with
- all provisions of Section 10 of RFC2026.
-
- Internet-Drafts are working documents of the Internet Engineering
- Task Force (IETF), its areas, and its working groups. Note that other
- groups may also distribute working documents as Internet-Drafts.
-
- Internet-Drafts are draft documents valid for a maximum of six months
- and may be updated, replaced, or obsoleted by other documents at any
- time. It is inappropriate to use Internet-Drafts as reference
- material or to cite them other than as "work in progress."
-
- The list of current Internet-Drafts can be accessed at http://
- www.ietf.org/ietf/1id-abstracts.txt.
-
- The list of Internet-Draft Shadow Directories can be accessed at
- http://www.ietf.org/shadow.html.
-
- This Internet-Draft will expire on March 31, 2004.
-
-Copyright Notice
-
- Copyright (C) The Internet Society (2003). All Rights Reserved.
-
-Abstract
-
- SSH is a protocol for secure remote login and other secure network
- services over an insecure network.
-
- This document describes the SSH Connection Protocol. It provides
- interactive login sessions, remote execution of commands, forwarded
- TCP/IP connections, and forwarded X11 connections. All of these
- channels are multiplexed into a single encrypted tunnel.
-
- The SSH Connection Protocol has been designed to run on top of the
- SSH transport layer and user authentication protocols.
-
-
-
-
-Ylonen & Moffat, Editor Expires March 31, 2004 [Page 1]
-
-Internet-Draft SSH Connection Protocol Oct 2003
-
-
-Table of Contents
-
- 1. Contributors . . . . . . . . . . . . . . . . . . . . . . . . 3
- 2. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3
- 3. Conventions Used in This Document . . . . . . . . . . . . . 3
- 4. Global Requests . . . . . . . . . . . . . . . . . . . . . . 3
- 5. Channel Mechanism . . . . . . . . . . . . . . . . . . . . . 4
- 5.1 Opening a Channel . . . . . . . . . . . . . . . . . . . . . 4
- 5.2 Data Transfer . . . . . . . . . . . . . . . . . . . . . . . 5
- 5.3 Closing a Channel . . . . . . . . . . . . . . . . . . . . . 6
- 5.4 Channel-Specific Requests . . . . . . . . . . . . . . . . . 7
- 6. Interactive Sessions . . . . . . . . . . . . . . . . . . . . 8
- 6.1 Opening a Session . . . . . . . . . . . . . . . . . . . . . 8
- 6.2 Requesting a Pseudo-Terminal . . . . . . . . . . . . . . . . 8
- 6.3 X11 Forwarding . . . . . . . . . . . . . . . . . . . . . . . 9
- 6.3.1 Requesting X11 Forwarding . . . . . . . . . . . . . . . . . 9
- 6.3.2 X11 Channels . . . . . . . . . . . . . . . . . . . . . . . . 10
- 6.4 Environment Variable Passing . . . . . . . . . . . . . . . . 10
- 6.5 Starting a Shell or a Command . . . . . . . . . . . . . . . 10
- 6.6 Session Data Transfer . . . . . . . . . . . . . . . . . . . 11
- 6.7 Window Dimension Change Message . . . . . . . . . . . . . . 12
- 6.8 Local Flow Control . . . . . . . . . . . . . . . . . . . . . 12
- 6.9 Signals . . . . . . . . . . . . . . . . . . . . . . . . . . 12
- 6.10 Returning Exit Status . . . . . . . . . . . . . . . . . . . 13
- 7. TCP/IP Port Forwarding . . . . . . . . . . . . . . . . . . . 14
- 7.1 Requesting Port Forwarding . . . . . . . . . . . . . . . . . 14
- 7.2 TCP/IP Forwarding Channels . . . . . . . . . . . . . . . . . 15
- 8. Encoding of Terminal Modes . . . . . . . . . . . . . . . . . 16
- 9. Summary of Message Numbers . . . . . . . . . . . . . . . . . 18
- 10. Security Considerations . . . . . . . . . . . . . . . . . . 18
- 11. iana cONSiderations . . . . . . . . . . . . . . . . . . . . 19
- 12. Intellectual Property . . . . . . . . . . . . . . . . . . . 19
- Normative References . . . . . . . . . . . . . . . . . . . . 19
- Informative References . . . . . . . . . . . . . . . . . . . 20
- Authors' Addresses . . . . . . . . . . . . . . . . . . . . . 20
- Intellectual Property and Copyright Statements . . . . . . . 21
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Ylonen & Moffat, Editor Expires March 31, 2004 [Page 2]
-
-Internet-Draft SSH Connection Protocol Oct 2003
-
-
-1. Contributors
-
- The major original contributors of this document were: Tatu Ylonen,
- Tero Kivinen, Timo J. Rinne, Sami Lehtinen (all of SSH Communications
- Security Corp), and Markku-Juhani O. Saarinen (University of
- Jyvaskyla)
-
- The document editor is: [email protected]. Comments on this
- internet draft should be sent to the IETF SECSH working group,
- details at: http://ietf.org/html.charters/secsh-charter.html
-
-2. Introduction
-
- The SSH Connection Protocol has been designed to run on top of the
- SSH transport layer and user authentication protocols. It provides
- interactive login sessions, remote execution of commands, forwarded
- TCP/IP connections, and forwarded X11 connections. The service name
- for this protocol is "ssh-connection".
-
- This document should be read only after reading the SSH architecture
- document [SSH-ARCH]. This document freely uses terminology and
- notation from the architecture document without reference or further
- explanation.
-
-3. Conventions Used in This Document
-
- The keywords "MUST", "MUST NOT", "REQUIRED", "SHOULD", "SHOULD NOT",
- and "MAY" that appear in this document are to be interpreted as
- described in [RFC2119].
-
- The used data types and terminology are specified in the architecture
- document [SSH-ARCH].
-
- The architecture document also discusses the algorithm naming
- conventions that MUST be used with the SSH protocols.
-
-4. Global Requests
-
- There are several kinds of requests that affect the state of the
- remote end "globally", independent of any channels. An example is a
- request to start TCP/IP forwarding for a specific port. All such
- requests use the following format.
-
- byte SSH_MSG_GLOBAL_REQUEST
- string request name (restricted to US-ASCII)
- boolean want reply
- ... request-specific data follows
-
-
-
-
-Ylonen & Moffat, Editor Expires March 31, 2004 [Page 3]
-
-Internet-Draft SSH Connection Protocol Oct 2003
-
-
- Request names follow the DNS extensibility naming convention outlined
- in [SSH-ARCH].
-
- The recipient will respond to this message with
- SSH_MSG_REQUEST_SUCCESS or SSH_MSG_REQUEST_FAILURE if `want reply' is
- TRUE.
-
- byte SSH_MSG_REQUEST_SUCCESS
- ..... response specific data
-
- Usually the response specific data is non-existent.
-
- If the recipient does not recognize or support the request, it simply
- responds with SSH_MSG_REQUEST_FAILURE.
-
- byte SSH_MSG_REQUEST_FAILURE
-
-
-5. Channel Mechanism
-
- All terminal sessions, forwarded connections, etc. are channels.
- Either side may open a channel. Multiple channels are multiplexed
- into a single connection.
-
- Channels are identified by numbers at each end. The number referring
- to a channel may be different on each side. Requests to open a
- channel contain the sender's channel number. Any other
- channel-related messages contain the recipient's channel number for
- the channel.
-
- Channels are flow-controlled. No data may be sent to a channel until
- a message is received to indicate that window space is available.
-
-5.1 Opening a Channel
-
- When either side wishes to open a new channel, it allocates a local
- number for the channel. It then sends the following message to the
- other side, and includes the local channel number and initial window
- size in the message.
-
- byte SSH_MSG_CHANNEL_OPEN
- string channel type (restricted to US-ASCII)
- uint32 sender channel
- uint32 initial window size
- uint32 maximum packet size
- ... channel type specific data follows
-
- The channel type is a name as described in the SSH architecture
-
-
-
-Ylonen & Moffat, Editor Expires March 31, 2004 [Page 4]
-
-Internet-Draft SSH Connection Protocol Oct 2003
-
-
- document, with similar extension mechanisms. `sender channel' is a
- local identifier for the channel used by the sender of this message.
- `initial window size' specifies how many bytes of channel data can be
- sent to the sender of this message without adjusting the window.
- `Maximum packet size' specifies the maximum size of an individual
- data packet that can be sent to the sender (for example, one might
- want to use smaller packets for interactive connections to get better
- interactive response on slow links).
-
- The remote side then decides whether it can open the channel, and
- responds with either
-
- byte SSH_MSG_CHANNEL_OPEN_CONFIRMATION
- uint32 recipient channel
- uint32 sender channel
- uint32 initial window size
- uint32 maximum packet size
- ... channel type specific data follows
-
- where `recipient channel' is the channel number given in the original
- open request, and `sender channel' is the channel number allocated by
- the other side, or
-
- byte SSH_MSG_CHANNEL_OPEN_FAILURE
- uint32 recipient channel
- uint32 reason code
- string additional textual information (ISO-10646 UTF-8 [RFC2279])
- string language tag (as defined in [RFC3066])
-
- If the recipient of the SSH_MSG_CHANNEL_OPEN message does not support
- the specified channel type, it simply responds with
- SSH_MSG_CHANNEL_OPEN_FAILURE. The client MAY show the additional
- information to the user. If this is done, the client software should
- take the precautions discussed in [SSH-ARCH].
-
- The following reason codes are defined:
-
- #define SSH_OPEN_ADMINISTRATIVELY_PROHIBITED 1
- #define SSH_OPEN_CONNECT_FAILED 2
- #define SSH_OPEN_UNKNOWN_CHANNEL_TYPE 3
- #define SSH_OPEN_RESOURCE_SHORTAGE 4
-
-
-5.2 Data Transfer
-
- The window size specifies how many bytes the other party can send
- before it must wait for the window to be adjusted. Both parties use
- the following message to adjust the window.
-
-
-
-Ylonen & Moffat, Editor Expires March 31, 2004 [Page 5]
-
-Internet-Draft SSH Connection Protocol Oct 2003
-
-
- byte SSH_MSG_CHANNEL_WINDOW_ADJUST
- uint32 recipient channel
- uint32 bytes to add
-
- After receiving this message, the recipient MAY send the given number
- of bytes more than it was previously allowed to send; the window size
- is incremented.
-
- Data transfer is done with messages of the following type.
-
- byte SSH_MSG_CHANNEL_DATA
- uint32 recipient channel
- string data
-
- The maximum amount of data allowed is the current window size. The
- window size is decremented by the amount of data sent. Both parties
- MAY ignore all extra data sent after the allowed window is empty.
-
- Additionally, some channels can transfer several types of data. An
- example of this is stderr data from interactive sessions. Such data
- can be passed with SSH_MSG_CHANNEL_EXTENDED_DATA messages, where a
- separate integer specifies the type of the data. The available types
- and their interpretation depend on the type of the channel.
-
- byte SSH_MSG_CHANNEL_EXTENDED_DATA
- uint32 recipient_channel
- uint32 data_type_code
- string data
-
- Data sent with these messages consumes the same window as ordinary
- data.
-
- Currently, only the following type is defined.
-
- #define SSH_EXTENDED_DATA_STDERR 1
-
-
-5.3 Closing a Channel
-
- When a party will no longer send more data to a channel, it SHOULD
- send SSH_MSG_CHANNEL_EOF.
-
- byte SSH_MSG_CHANNEL_EOF
- uint32 recipient_channel
-
- No explicit response is sent to this message; however, the
- application may send EOF to whatever is at the other end of the
- channel. Note that the channel remains open after this message, and
-
-
-
-Ylonen & Moffat, Editor Expires March 31, 2004 [Page 6]
-
-Internet-Draft SSH Connection Protocol Oct 2003
-
-
- more data may still be sent in the other direction. This message
- does not consume window space and can be sent even if no window space
- is available.
-
- When either party wishes to terminate the channel, it sends
- SSH_MSG_CHANNEL_CLOSE. Upon receiving this message, a party MUST
- send back a SSH_MSG_CHANNEL_CLOSE unless it has already sent this
- message for the channel. The channel is considered closed for a
- party when it has both sent and received SSH_MSG_CHANNEL_CLOSE, and
- the party may then reuse the channel number. A party MAY send
- SSH_MSG_CHANNEL_CLOSE without having sent or received
- SSH_MSG_CHANNEL_EOF.
-
- byte SSH_MSG_CHANNEL_CLOSE
- uint32 recipient_channel
-
- This message does not consume window space and can be sent even if no
- window space is available.
-
- It is recommended that any data sent before this message is delivered
- to the actual destination, if possible.
-
-5.4 Channel-Specific Requests
-
- Many channel types have extensions that are specific to that
- particular channel type. An example is requesting a pty (pseudo
- terminal) for an interactive session.
-
- All channel-specific requests use the following format.
-
- byte SSH_MSG_CHANNEL_REQUEST
- uint32 recipient channel
- string request type (restricted to US-ASCII)
- boolean want reply
- ... type-specific data
-
- If want reply is FALSE, no response will be sent to the request.
- Otherwise, the recipient responds with either SSH_MSG_CHANNEL_SUCCESS
- or SSH_MSG_CHANNEL_FAILURE, or request-specific continuation
- messages. If the request is not recognized or is not supported for
- the channel, SSH_MSG_CHANNEL_FAILURE is returned.
-
- This message does not consume window space and can be sent even if no
- window space is available. Request types are local to each channel
- type.
-
- The client is allowed to send further messages without waiting for
- the response to the request.
-
-
-
-Ylonen & Moffat, Editor Expires March 31, 2004 [Page 7]
-
-Internet-Draft SSH Connection Protocol Oct 2003
-
-
- request type names follow the DNS extensibility naming convention
- outlined in [SSH-ARCH]
-
- byte SSH_MSG_CHANNEL_SUCCESS
- uint32 recipient_channel
-
-
- byte SSH_MSG_CHANNEL_FAILURE
- uint32 recipient_channel
-
- These messages do not consume window space and can be sent even if no
- window space is available.
-
-6. Interactive Sessions
-
- A session is a remote execution of a program. The program may be a
- shell, an application, a system command, or some built-in subsystem.
- It may or may not have a tty, and may or may not involve X11
- forwarding. Multiple sessions can be active simultaneously.
-
-6.1 Opening a Session
-
- A session is started by sending the following message.
-
- byte SSH_MSG_CHANNEL_OPEN
- string "session"
- uint32 sender channel
- uint32 initial window size
- uint32 maximum packet size
-
- Client implementations SHOULD reject any session channel open
- requests to make it more difficult for a corrupt server to attack the
- client.
-
-6.2 Requesting a Pseudo-Terminal
-
- A pseudo-terminal can be allocated for the session by sending the
- following message.
-
- byte SSH_MSG_CHANNEL_REQUEST
- uint32 recipient_channel
- string "pty-req"
- boolean want_reply
- string TERM environment variable value (e.g., vt100)
- uint32 terminal width, characters (e.g., 80)
- uint32 terminal height, rows (e.g., 24)
- uint32 terminal width, pixels (e.g., 640)
- uint32 terminal height, pixels (e.g., 480)
-
-
-
-Ylonen & Moffat, Editor Expires March 31, 2004 [Page 8]
-
-Internet-Draft SSH Connection Protocol Oct 2003
-
-
- string encoded terminal modes
-
- The encoding of terminal modes is described in Section Encoding of
- Terminal Modes (Section 8). Zero dimension parameters MUST be
- ignored. The character/row dimensions override the pixel dimensions
- (when nonzero). Pixel dimensions refer to the drawable area of the
- window.
-
- The dimension parameters are only informational.
-
- The client SHOULD ignore pty requests.
-
-6.3 X11 Forwarding
-
-6.3.1 Requesting X11 Forwarding
-
- X11 forwarding may be requested for a session by sending
-
- byte SSH_MSG_CHANNEL_REQUEST
- uint32 recipient channel
- string "x11-req"
- boolean want reply
- boolean single connection
- string x11 authentication protocol
- string x11 authentication cookie
- uint32 x11 screen number
-
- It is recommended that the authentication cookie that is sent be a
- fake, random cookie, and that the cookie is checked and replaced by
- the real cookie when a connection request is received.
-
- X11 connection forwarding should stop when the session channel is
- closed; however, already opened forwardings should not be
- automatically closed when the session channel is closed.
-
- If `single connection' is TRUE, only a single connection should be
- forwarded. No more connections will be forwarded after the first, or
- after the session channel has been closed.
-
- The "x11 authentication protocol" is the name of the X11
- authentication method used, e.g. "MIT-MAGIC-COOKIE-1".
-
- The x11 authentication cookie MUST be hexadecimal encoded.
-
- X Protocol is documented in [SCHEIFLER].
-
-
-
-
-
-
-Ylonen & Moffat, Editor Expires March 31, 2004 [Page 9]
-
-Internet-Draft SSH Connection Protocol Oct 2003
-
-
-6.3.2 X11 Channels
-
- X11 channels are opened with a channel open request. The resulting
- channels are independent of the session, and closing the session
- channel does not close the forwarded X11 channels.
-
- byte SSH_MSG_CHANNEL_OPEN
- string "x11"
- uint32 sender channel
- uint32 initial window size
- uint32 maximum packet size
- string originator address (e.g. "192.168.7.38")
- uint32 originator port
-
- The recipient should respond with SSH_MSG_CHANNEL_OPEN_CONFIRMATION
- or SSH_MSG_CHANNEL_OPEN_FAILURE.
-
- Implementations MUST reject any X11 channel open requests if they
- have not requested X11 forwarding.
-
-6.4 Environment Variable Passing
-
- Environment variables may be passed to the shell/command to be
- started later. Uncontrolled setting of environment variables in a
- privileged process can be a security hazard. It is recommended that
- implementations either maintain a list of allowable variable names or
- only set environment variables after the server process has dropped
- sufficient privileges.
-
- byte SSH_MSG_CHANNEL_REQUEST
- uint32 recipient channel
- string "env"
- boolean want reply
- string variable name
- string variable value
-
-
-6.5 Starting a Shell or a Command
-
- Once the session has been set up, a program is started at the remote
- end. The program can be a shell, an application program or a
- subsystem with a host-independent name. Only one of these requests
- can succeed per channel.
-
- byte SSH_MSG_CHANNEL_REQUEST
- uint32 recipient channel
- string "shell"
- boolean want reply
-
-
-
-Ylonen & Moffat, Editor Expires March 31, 2004 [Page 10]
-
-Internet-Draft SSH Connection Protocol Oct 2003
-
-
- This message will request the user's default shell (typically defined
- in /etc/passwd in UNIX systems) to be started at the other end.
-
- byte SSH_MSG_CHANNEL_REQUEST
- uint32 recipient channel
- string "exec"
- boolean want reply
- string command
-
- This message will request the server to start the execution of the
- given command. The command string may contain a path. Normal
- precautions MUST be taken to prevent the execution of unauthorized
- commands.
-
- byte SSH_MSG_CHANNEL_REQUEST
- uint32 recipient channel
- string "subsystem"
- boolean want reply
- string subsystem name
-
- This last form executes a predefined subsystem. It is expected that
- these will include a general file transfer mechanism, and possibly
- other features. Implementations may also allow configuring more such
- mechanisms. As the user's shell is usually used to execute the
- subsystem, it is advisable for the subsystem protocol to have a
- "magic cookie" at the beginning of the protocol transaction to
- distinguish it from arbitrary output generated by shell
- initialization scripts etc. This spurious output from the shell may
- be filtered out either at the server or at the client.
-
- The server SHOULD not halt the execution of the protocol stack when
- starting a shell or a program. All input and output from these SHOULD
- be redirected to the channel or to the encrypted tunnel.
-
- It is RECOMMENDED to request and check the reply for these messages.
- The client SHOULD ignore these messages.
-
- Subsystem names follow the DNS extensibility naming convention
- outlined in [SSH-ARCH].
-
-6.6 Session Data Transfer
-
- Data transfer for a session is done using SSH_MSG_CHANNEL_DATA and
- SSH_MSG_CHANNEL_EXTENDED_DATA packets and the window mechanism. The
- extended data type SSH_EXTENDED_DATA_STDERR has been defined for
- stderr data.
-
-
-
-
-
-Ylonen & Moffat, Editor Expires March 31, 2004 [Page 11]
-
-Internet-Draft SSH Connection Protocol Oct 2003
-
-
-6.7 Window Dimension Change Message
-
- When the window (terminal) size changes on the client side, it MAY
- send a message to the other side to inform it of the new dimensions.
-
- byte SSH_MSG_CHANNEL_REQUEST
- uint32 recipient_channel
- string "window-change"
- boolean FALSE
- uint32 terminal width, columns
- uint32 terminal height, rows
- uint32 terminal width, pixels
- uint32 terminal height, pixels
-
- No response SHOULD be sent to this message.
-
-6.8 Local Flow Control
-
- On many systems, it is possible to determine if a pseudo-terminal is
- using control-S/control-Q flow control. When flow control is
- allowed, it is often desirable to do the flow control at the client
- end to speed up responses to user requests. This is facilitated by
- the following notification. Initially, the server is responsible for
- flow control. (Here, again, client means the side originating the
- session, and server means the other side.)
-
- The message below is used by the server to inform the client when it
- can or cannot perform flow control (control-S/control-Q processing).
- If `client can do' is TRUE, the client is allowed to do flow control
- using control-S and control-Q. The client MAY ignore this message.
-
- byte SSH_MSG_CHANNEL_REQUEST
- uint32 recipient channel
- string "xon-xoff"
- boolean FALSE
- boolean client can do
-
- No response is sent to this message.
-
-6.9 Signals
-
- A signal can be delivered to the remote process/service using the
- following message. Some systems may not implement signals, in which
- case they SHOULD ignore this message.
-
- byte SSH_MSG_CHANNEL_REQUEST
- uint32 recipient channel
- string "signal"
-
-
-
-Ylonen & Moffat, Editor Expires March 31, 2004 [Page 12]
-
-Internet-Draft SSH Connection Protocol Oct 2003
-
-
- boolean FALSE
- string signal name without the "SIG" prefix.
-
- Signal names will be encoded as discussed in the "exit-signal"
- SSH_MSG_CHANNEL_REQUEST.
-
-6.10 Returning Exit Status
-
- When the command running at the other end terminates, the following
- message can be sent to return the exit status of the command.
- Returning the status is RECOMMENDED. No acknowledgment is sent for
- this message. The channel needs to be closed with
- SSH_MSG_CHANNEL_CLOSE after this message.
-
- The client MAY ignore these messages.
-
- byte SSH_MSG_CHANNEL_REQUEST
- uint32 recipient_channel
- string "exit-status"
- boolean FALSE
- uint32 exit_status
-
- The remote command may also terminate violently due to a signal.
- Such a condition can be indicated by the following message. A zero
- exit_status usually means that the command terminated successfully.
-
- byte SSH_MSG_CHANNEL_REQUEST
- uint32 recipient channel
- string "exit-signal"
- boolean FALSE
- string signal name without the "SIG" prefix.
- boolean core dumped
- string error message (ISO-10646 UTF-8)
- string language tag (as defined in [RFC3066])
-
- The signal name is one of the following (these are from [POSIX])
-
- ABRT
- ALRM
- FPE
- HUP
- ILL
- INT
- KILL
- PIPE
- QUIT
- SEGV
- TERM
-
-
-
-Ylonen & Moffat, Editor Expires March 31, 2004 [Page 13]
-
-Internet-Draft SSH Connection Protocol Oct 2003
-
-
- USR1
- USR2
-
- Additional signal names MAY be sent in the format "sig-name@xyz",
- where `sig-name' and `xyz' may be anything a particular implementor
- wants (except the `@' sign). However, it is suggested that if a
- `configure' script is used, the non-standard signal names it finds be
- encoded as "[email protected]", where `SIG' is the signal name
- without the "SIG" prefix, and `xyz' be the host type, as determined
- by `config.guess'.
-
- The `error message' contains an additional explanation of the error
- message. The message may consist of multiple lines. The client
- software MAY display this message to the user. If this is done, the
- client software should take the precautions discussed in [SSH-ARCH].
-
-7. TCP/IP Port Forwarding
-
-7.1 Requesting Port Forwarding
-
- A party need not explicitly request forwardings from its own end to
- the other direction. However, if it wishes that connections to a
- port on the other side be forwarded to the local side, it must
- explicitly request this.
-
-
- byte SSH_MSG_GLOBAL_REQUEST
- string "tcpip-forward"
- boolean want reply
- string address to bind (e.g. "0.0.0.0")
- uint32 port number to bind
-
- `Address to bind' and `port number to bind' specify the IP address
- and port to which the socket to be listened is bound. The address
- should be "0.0.0.0" if connections are allowed from anywhere. (Note
- that the client can still filter connections based on information
- passed in the open request.)
-
- Implementations should only allow forwarding privileged ports if the
- user has been authenticated as a privileged user.
-
- Client implementations SHOULD reject these messages; they are
- normally only sent by the client.
-
-
- If a client passes 0 as port number to bind and has want reply TRUE
- then the server allocates the next available unprivileged port number
- and replies with the following message, otherwise there is no
-
-
-
-Ylonen & Moffat, Editor Expires March 31, 2004 [Page 14]
-
-Internet-Draft SSH Connection Protocol Oct 2003
-
-
- response specific data.
-
-
- byte SSH_MSG_GLOBAL_REQUEST_SUCCESS
- uint32 port that was bound on the server
-
- A port forwarding can be cancelled with the following message. Note
- that channel open requests may be received until a reply to this
- message is received.
-
- byte SSH_MSG_GLOBAL_REQUEST
- string "cancel-tcpip-forward"
- boolean want reply
- string address_to_bind (e.g. "127.0.0.1")
- uint32 port number to bind
-
- Client implementations SHOULD reject these messages; they are
- normally only sent by the client.
-
-7.2 TCP/IP Forwarding Channels
-
- When a connection comes to a port for which remote forwarding has
- been requested, a channel is opened to forward the port to the other
- side.
-
- byte SSH_MSG_CHANNEL_OPEN
- string "forwarded-tcpip"
- uint32 sender channel
- uint32 initial window size
- uint32 maximum packet size
- string address that was connected
- uint32 port that was connected
- string originator IP address
- uint32 originator port
-
- Implementations MUST reject these messages unless they have
- previously requested a remote TCP/IP port forwarding with the given
- port number.
-
- When a connection comes to a locally forwarded TCP/IP port, the
- following packet is sent to the other side. Note that these messages
- MAY be sent also for ports for which no forwarding has been
- explicitly requested. The receiving side must decide whether to
- allow the forwarding.
-
- byte SSH_MSG_CHANNEL_OPEN
- string "direct-tcpip"
- uint32 sender channel
-
-
-
-Ylonen & Moffat, Editor Expires March 31, 2004 [Page 15]
-
-Internet-Draft SSH Connection Protocol Oct 2003
-
-
- uint32 initial window size
- uint32 maximum packet size
- string host to connect
- uint32 port to connect
- string originator IP address
- uint32 originator port
-
- `Host to connect' and `port to connect' specify the TCP/IP host and
- port where the recipient should connect the channel. `Host to
- connect' may be either a domain name or a numeric IP address.
-
- `Originator IP address' is the numeric IP address of the machine
- where the connection request comes from, and `originator port' is the
- port on the originator host from where the connection came from.
-
- Forwarded TCP/IP channels are independent of any sessions, and
- closing a session channel does not in any way imply that forwarded
- connections should be closed.
-
- Client implementations SHOULD reject direct TCP/IP open requests for
- security reasons.
-
-8. Encoding of Terminal Modes
-
- Terminal modes (as passed in a pty request) are encoded into a byte
- stream. It is intended that the coding be portable across different
- environments.
-
- The tty mode description is a stream of bytes. The stream consists
- of opcode-argument pairs. It is terminated by opcode TTY_OP_END (0).
- Opcodes 1 to 159 have a single uint32 argument. Opcodes 160 to 255
- are not yet defined, and cause parsing to stop (they should only be
- used after any other data).
-
- The client SHOULD put in the stream any modes it knows about, and the
- server MAY ignore any modes it does not know about. This allows some
- degree of machine-independence, at least between systems that use a
- POSIX-like tty interface. The protocol can support other systems as
- well, but the client may need to fill reasonable values for a number
- of parameters so the server pty gets set to a reasonable mode (the
- server leaves all unspecified mode bits in their default values, and
- only some combinations make sense).
-
- The following opcodes have been defined. The naming of opcodes
- mostly follows the POSIX terminal mode flags.
-
- 0 TTY_OP_END Indicates end of options.
- 1 VINTR Interrupt character; 255 if none. Similarly for the
-
-
-
-Ylonen & Moffat, Editor Expires March 31, 2004 [Page 16]
-
-Internet-Draft SSH Connection Protocol Oct 2003
-
-
- other characters. Not all of these characters are
- supported on all systems.
- 2 VQUIT The quit character (sends SIGQUIT signal on POSIX
- systems).
- 3 VERASE Erase the character to left of the cursor.
- 4 VKILL Kill the current input line.
- 5 VEOF End-of-file character (sends EOF from the terminal).
- 6 VEOL End-of-line character in addition to carriage return
- and/or linefeed.
- 7 VEOL2 Additional end-of-line character.
- 8 VSTART Continues paused output (normally control-Q).
- 9 VSTOP Pauses output (normally control-S).
- 10 VSUSP Suspends the current program.
- 11 VDSUSP Another suspend character.
- 12 VREPRINT Reprints the current input line.
- 13 VWERASE Erases a word left of cursor.
- 14 VLNEXT Enter the next character typed literally, even if it
- is a special character
- 15 VFLUSH Character to flush output.
- 16 VSWTCH Switch to a different shell layer.
- 17 VSTATUS Prints system status line (load, command, pid etc).
- 18 VDISCARD Toggles the flushing of terminal output.
- 30 IGNPAR The ignore parity flag. The parameter SHOULD be 0 if
- this flag is FALSE set, and 1 if it is TRUE.
- 31 PARMRK Mark parity and framing errors.
- 32 INPCK Enable checking of parity errors.
- 33 ISTRIP Strip 8th bit off characters.
- 34 INLCR Map NL into CR on input.
- 35 IGNCR Ignore CR on input.
- 36 ICRNL Map CR to NL on input.
- 37 IUCLC Translate uppercase characters to lowercase.
- 38 IXON Enable output flow control.
- 39 IXANY Any char will restart after stop.
- 40 IXOFF Enable input flow control.
- 41 IMAXBEL Ring bell on input queue full.
- 50 ISIG Enable signals INTR, QUIT, [D]SUSP.
- 51 ICANON Canonicalize input lines.
- 52 XCASE Enable input and output of uppercase characters by
- preceding their lowercase equivalents with `\'.
- 53 ECHO Enable echoing.
- 54 ECHOE Visually erase chars.
- 55 ECHOK Kill character discards current line.
- 56 ECHONL Echo NL even if ECHO is off.
- 57 NOFLSH Don't flush after interrupt.
- 58 TOSTOP Stop background jobs from output.
- 59 IEXTEN Enable extensions.
- 60 ECHOCTL Echo control characters as ^(Char).
- 61 ECHOKE Visual erase for line kill.
-
-
-
-Ylonen & Moffat, Editor Expires March 31, 2004 [Page 17]
-
-Internet-Draft SSH Connection Protocol Oct 2003
-
-
- 62 PENDIN Retype pending input.
- 70 OPOST Enable output processing.
- 71 OLCUC Convert lowercase to uppercase.
- 72 ONLCR Map NL to CR-NL.
- 73 OCRNL Translate carriage return to newline (output).
- 74 ONOCR Translate newline to carriage return-newline
- (output).
- 75 ONLRET Newline performs a carriage return (output).
- 90 CS7 7 bit mode.
- 91 CS8 8 bit mode.
- 92 PARENB Parity enable.
- 93 PARODD Odd parity, else even.
-
- 128 TTY_OP_ISPEED Specifies the input baud rate in bits per second.
- 129 TTY_OP_OSPEED Specifies the output baud rate in bits per second.
-
-
-9. Summary of Message Numbers
-
- #define SSH_MSG_GLOBAL_REQUEST 80
- #define SSH_MSG_REQUEST_SUCCESS 81
- #define SSH_MSG_REQUEST_FAILURE 82
- #define SSH_MSG_CHANNEL_OPEN 90
- #define SSH_MSG_CHANNEL_OPEN_CONFIRMATION 91
- #define SSH_MSG_CHANNEL_OPEN_FAILURE 92
- #define SSH_MSG_CHANNEL_WINDOW_ADJUST 93
- #define SSH_MSG_CHANNEL_DATA 94
- #define SSH_MSG_CHANNEL_EXTENDED_DATA 95
- #define SSH_MSG_CHANNEL_EOF 96
- #define SSH_MSG_CHANNEL_CLOSE 97
- #define SSH_MSG_CHANNEL_REQUEST 98
- #define SSH_MSG_CHANNEL_SUCCESS 99
- #define SSH_MSG_CHANNEL_FAILURE 100
-
-
-10. Security Considerations
-
- This protocol is assumed to run on top of a secure, authenticated
- transport. User authentication and protection against network-level
- attacks are assumed to be provided by the underlying protocols.
-
- It is RECOMMENDED that implementations disable all the potentially
- dangerous features (e.g. agent forwarding, X11 forwarding, and TCP/IP
- forwarding) if the host key has changed.
-
- Full security considerations for this protocol are provided in
- Section 8 of [SSH-ARCH]
-
-
-
-
-Ylonen & Moffat, Editor Expires March 31, 2004 [Page 18]
-
-Internet-Draft SSH Connection Protocol Oct 2003
-
-
-11. iana cONSiderations
-
- This document is part of a set, the IANA considerations for the SSH
- protocol as defined in [SSH-ARCH], [SSH-TRANS], [SSH-USERAUTH],
- [SSH-CONNECT] are detailed in [SSH-NUMBERS].
-
-12. Intellectual Property
-
- The IETF takes no position regarding the validity or scope of any
- intellectual property or other rights that might be claimed to
- pertain to the implementation or use of the technology described in
- this document or the extent to which any license under such rights
- might or might not be available; neither does it represent that it
- has made any effort to identify any such rights. Information on the
- IETF's procedures with respect to rights in standards-track and
- standards-related documentation can be found in BCP-11. Copies of
- claims of rights made available for publication and any assurances of
- licenses to be made available, or the result of an attempt made to
- obtain a general license or permission for the use of such
- proprietary rights by implementers or users of this specification can
- be obtained from the IETF Secretariat.
-
- The IETF has been notified of intellectual property rights claimed in
- regard to some or all of the specification contained in this
- document. For more information consult the online list of claimed
- rights.
-
-Normative References
-
- [SSH-ARCH]
- Ylonen, T., "SSH Protocol Architecture", I-D
- draft-ietf-architecture-15.txt, Oct 2003.
-
- [SSH-TRANS]
- Ylonen, T., "SSH Transport Layer Protocol", I-D
- draft-ietf-transport-17.txt, Oct 2003.
-
- [SSH-USERAUTH]
- Ylonen, T., "SSH Authentication Protocol", I-D
- draft-ietf-userauth-18.txt, Oct 2003.
-
- [SSH-CONNECT]
- Ylonen, T., "SSH Connection Protocol", I-D
- draft-ietf-connect-18.txt, Oct 2003.
-
- [SSH-NUMBERS]
- Lehtinen, S. and D. Moffat, "SSH Protocol Assigned
- Numbers", I-D draft-ietf-secsh-assignednumbers-05.txt, Oct
-
-
-
-Ylonen & Moffat, Editor Expires March 31, 2004 [Page 19]
-
-Internet-Draft SSH Connection Protocol Oct 2003
-
-
- 2003.
-
- [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
- Requirement Levels", BCP 14, RFC 2119, March 1997.
-
-Informative References
-
- [RFC3066] Alvestrand, H., "Tags for the Identification of
- Languages", BCP 47, RFC 3066, January 2001.
-
- [RFC1884] Hinden, R. and S. Deering, "IP Version 6 Addressing
- Architecture", RFC 1884, December 1995.
-
- [RFC2279] Yergeau, F., "UTF-8, a transformation format of ISO
- 10646", RFC 2279, January 1998.
-
- [SCHEIFLER]
- Scheifler, R., "X Window System : The Complete Reference
- to Xlib, X Protocol, Icccm, Xlfd, 3rd edition.", Digital
- Press ISBN 1555580882, Feburary 1992.
-
- [POSIX] ISO/IEC, 9945-1., "Information technology -- Portable
- Operating System Interface (POSIX)-Part 1: System
- Application Program Interface (API) C Language", ANSI/IEE
- Std 1003.1, July 1996.
-
-
-Authors' Addresses
-
- Tatu Ylonen
- SSH Communications Security Corp
- Fredrikinkatu 42
- HELSINKI FIN-00100
- Finland
-
-
-
- Darren J. Moffat (editor)
- Sun Microsystems, Inc
- 17 Network Circle
- Menlo Park CA 94025
- USA
-
-
-
-
-
-
-
-Ylonen & Moffat, Editor Expires March 31, 2004 [Page 20]
-
-Internet-Draft SSH Connection Protocol Oct 2003
-
-
-Intellectual Property Statement
-
- The IETF takes no position regarding the validity or scope of any
- intellectual property or other rights that might be claimed to
- pertain to the implementation or use of the technology described in
- this document or the extent to which any license under such rights
- might or might not be available; neither does it represent that it
- has made any effort to identify any such rights. Information on the
- IETF's procedures with respect to rights in standards-track and
- standards-related documentation can be found in BCP-11. Copies of
- claims of rights made available for publication and any assurances of
- licenses to be made available, or the result of an attempt made to
- obtain a general license or permission for the use of such
- proprietary rights by implementors or users of this specification can
- be obtained from the IETF Secretariat.
-
- The IETF invites any interested party to bring to its attention any
- copyrights, patents or patent applications, or other proprietary
- rights which may cover technology that may be required to practice
- this standard. Please address the information to the IETF Executive
- Director.
-
- The IETF has been notified of intellectual property rights claimed in
- regard to some or all of the specification contained in this
- document. For more information consult the online list of claimed
- rights.
-
-
-Full Copyright Statement
-
- Copyright (C) The Internet Society (2003). All Rights Reserved.
-
- This document and translations of it may be copied and furnished to
- others, and derivative works that comment on or otherwise explain it
- or assist in its implementation may be prepared, copied, published
- and distributed, in whole or in part, without restriction of any
- kind, provided that the above copyright notice and this paragraph are
- included on all such copies and derivative works. However, this
- document itself may not be modified in any way, such as by removing
- the copyright notice or references to the Internet Society or other
- Internet organizations, except as needed for the purpose of
- developing Internet standards in which case the procedures for
- copyrights defined in the Internet Standards process must be
- followed, or as required to translate it into languages other than
- English.
-
- The limited permissions granted above are perpetual and will not be
- revoked by the Internet Society or its successors or assignees.
-
-
-
-Ylonen & Moffat, Editor Expires March 31, 2004 [Page 21]
-
-Internet-Draft SSH Connection Protocol Oct 2003
-
-
- This document and the information contained herein is provided on an
- "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
- TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
- BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
- HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
- MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
-
-
-Acknowledgment
-
- Funding for the RFC Editor function is currently provided by the
- Internet Society.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Ylonen & Moffat, Editor Expires March 31, 2004 [Page 22] \ No newline at end of file
diff --git a/lib/ssh/doc/standard/draft-ietf-secsh-filexfer-02.2.ps b/lib/ssh/doc/standard/draft-ietf-secsh-filexfer-02.2.ps
deleted file mode 100644
index 06c91bf8cd..0000000000
--- a/lib/ssh/doc/standard/draft-ietf-secsh-filexfer-02.2.ps
+++ /dev/null
@@ -1,2853 +0,0 @@
-%!PS-Adobe-3.0
-%%BoundingBox: 75 0 595 747
-%%Title: Enscript Output
-%%For: Magnus Thoang
-%%Creator: GNU enscript 1.6.1
-%%CreationDate: Wed Nov 12 12:26:07 2003
-%%Orientation: Portrait
-%%Pages: 15 0
-%%DocumentMedia: A4 595 842 0 () ()
-%%DocumentNeededResources: (atend)
-%%EndComments
-%%BeginProlog
-%%BeginProcSet: PStoPS 1 15
-userdict begin
-[/showpage/erasepage/copypage]{dup where{pop dup load
- type/operatortype eq{1 array cvx dup 0 3 index cvx put
- bind def}{pop}ifelse}{pop}ifelse}forall
-[/letter/legal/executivepage/a4/a4small/b5/com10envelope
- /monarchenvelope/c5envelope/dlenvelope/lettersmall/note
- /folio/quarto/a5]{dup where{dup wcheck{exch{}put}
- {pop{}def}ifelse}{pop}ifelse}forall
-/setpagedevice {pop}bind 1 index where{dup wcheck{3 1 roll put}
- {pop def}ifelse}{def}ifelse
-/PStoPSmatrix matrix currentmatrix def
-/PStoPSxform matrix def/PStoPSclip{clippath}def
-/defaultmatrix{PStoPSmatrix exch PStoPSxform exch concatmatrix}bind def
-/initmatrix{matrix defaultmatrix setmatrix}bind def
-/initclip[{matrix currentmatrix PStoPSmatrix setmatrix
- [{currentpoint}stopped{$error/newerror false put{newpath}}
- {/newpath cvx 3 1 roll/moveto cvx 4 array astore cvx}ifelse]
- {[/newpath cvx{/moveto cvx}{/lineto cvx}
- {/curveto cvx}{/closepath cvx}pathforall]cvx exch pop}
- stopped{$error/errorname get/invalidaccess eq{cleartomark
- $error/newerror false put cvx exec}{stop}ifelse}if}bind aload pop
- /initclip dup load dup type dup/operatortype eq{pop exch pop}
- {dup/arraytype eq exch/packedarraytype eq or
- {dup xcheck{exch pop aload pop}{pop cvx}ifelse}
- {pop cvx}ifelse}ifelse
- {newpath PStoPSclip clip newpath exec setmatrix} bind aload pop]cvx def
-/initgraphics{initmatrix newpath initclip 1 setlinewidth
- 0 setlinecap 0 setlinejoin []0 setdash 0 setgray
- 10 setmiterlimit}bind def
-end
-%%EndProcSet
-%%BeginResource: procset Enscript-Prolog 1.6 1
-%
-% Procedures.
-%
-
-/_S { % save current state
- /_s save def
-} def
-/_R { % restore from saved state
- _s restore
-} def
-
-/S { % showpage protecting gstate
- gsave
- showpage
- grestore
-} bind def
-
-/MF { % fontname newfontname -> - make a new encoded font
- /newfontname exch def
- /fontname exch def
-
- /fontdict fontname findfont def
- /newfont fontdict maxlength dict def
-
- fontdict {
- exch
- dup /FID eq {
- % skip FID pair
- pop pop
- } {
- % copy to the new font dictionary
- exch newfont 3 1 roll put
- } ifelse
- } forall
-
- newfont /FontName newfontname put
-
- % insert only valid encoding vectors
- encoding_vector length 256 eq {
- newfont /Encoding encoding_vector put
- } if
-
- newfontname newfont definefont pop
-} def
-
-/SF { % fontname width height -> - set a new font
- /height exch def
- /width exch def
-
- findfont
- [width 0 0 height 0 0] makefont setfont
-} def
-
-/SUF { % fontname width height -> - set a new user font
- /height exch def
- /width exch def
-
- /F-gs-user-font MF
- /F-gs-user-font width height SF
-} def
-
-/M {moveto} bind def
-/s {show} bind def
-
-/Box { % x y w h -> - define box path
- /d_h exch def /d_w exch def /d_y exch def /d_x exch def
- d_x d_y moveto
- d_w 0 rlineto
- 0 d_h rlineto
- d_w neg 0 rlineto
- closepath
-} def
-
-/bgs { % x y height blskip gray str -> - show string with bg color
- /str exch def
- /gray exch def
- /blskip exch def
- /height exch def
- /y exch def
- /x exch def
-
- gsave
- x y blskip sub str stringwidth pop height Box
- gray setgray
- fill
- grestore
- x y M str s
-} def
-
-% Highlight bars.
-/highlight_bars { % nlines lineheight output_y_margin gray -> -
- gsave
- setgray
- /ymarg exch def
- /lineheight exch def
- /nlines exch def
-
- % This 2 is just a magic number to sync highlight lines to text.
- 0 d_header_y ymarg sub 2 sub translate
-
- /cw d_output_w cols div def
- /nrows d_output_h ymarg 2 mul sub lineheight div cvi def
-
- % for each column
- 0 1 cols 1 sub {
- cw mul /xp exch def
-
- % for each rows
- 0 1 nrows 1 sub {
- /rn exch def
- rn lineheight mul neg /yp exch def
- rn nlines idiv 2 mod 0 eq {
- % Draw highlight bar. 4 is just a magic indentation.
- xp 4 add yp cw 8 sub lineheight neg Box fill
- } if
- } for
- } for
-
- grestore
-} def
-
-% Line highlight bar.
-/line_highlight { % x y width height gray -> -
- gsave
- /gray exch def
- Box gray setgray fill
- grestore
-} def
-
-% Column separator lines.
-/column_lines {
- gsave
- .1 setlinewidth
- 0 d_footer_h translate
- /cw d_output_w cols div def
- 1 1 cols 1 sub {
- cw mul 0 moveto
- 0 d_output_h rlineto stroke
- } for
- grestore
-} def
-
-% Column borders.
-/column_borders {
- gsave
- .1 setlinewidth
- 0 d_footer_h moveto
- 0 d_output_h rlineto
- d_output_w 0 rlineto
- 0 d_output_h neg rlineto
- closepath stroke
- grestore
-} def
-
-% Do the actual underlay drawing
-/draw_underlay {
- ul_style 0 eq {
- ul_str true charpath stroke
- } {
- ul_str show
- } ifelse
-} def
-
-% Underlay
-/underlay { % - -> -
- gsave
- 0 d_page_h translate
- d_page_h neg d_page_w atan rotate
-
- ul_gray setgray
- ul_font setfont
- /dw d_page_h dup mul d_page_w dup mul add sqrt def
- ul_str stringwidth pop dw exch sub 2 div ul_h_ptsize -2 div moveto
- draw_underlay
- grestore
-} def
-
-/user_underlay { % - -> -
- gsave
- ul_x ul_y translate
- ul_angle rotate
- ul_gray setgray
- ul_font setfont
- 0 0 ul_h_ptsize 2 div sub moveto
- draw_underlay
- grestore
-} def
-
-% Page prefeed
-/page_prefeed { % bool -> -
- statusdict /prefeed known {
- statusdict exch /prefeed exch put
- } {
- pop
- } ifelse
-} def
-
-% Wrapped line markers
-/wrapped_line_mark { % x y charwith charheight type -> -
- /type exch def
- /h exch def
- /w exch def
- /y exch def
- /x exch def
-
- type 2 eq {
- % Black boxes (like TeX does)
- gsave
- 0 setlinewidth
- x w 4 div add y M
- 0 h rlineto w 2 div 0 rlineto 0 h neg rlineto
- closepath fill
- grestore
- } {
- type 3 eq {
- % Small arrows
- gsave
- .2 setlinewidth
- x w 2 div add y h 2 div add M
- w 4 div 0 rlineto
- x w 4 div add y lineto stroke
-
- x w 4 div add w 8 div add y h 4 div add M
- x w 4 div add y lineto
- w 4 div h 8 div rlineto stroke
- grestore
- } {
- % do nothing
- } ifelse
- } ifelse
-} def
-
-% EPSF import.
-
-/BeginEPSF {
- /b4_Inc_state save def % Save state for cleanup
- /dict_count countdictstack def % Count objects on dict stack
- /op_count count 1 sub def % Count objects on operand stack
- userdict begin
- /showpage { } def
- 0 setgray 0 setlinecap
- 1 setlinewidth 0 setlinejoin
- 10 setmiterlimit [ ] 0 setdash newpath
- /languagelevel where {
- pop languagelevel
- 1 ne {
- false setstrokeadjust false setoverprint
- } if
- } if
-} bind def
-
-/EndEPSF {
- count op_count sub { pos } repeat % Clean up stacks
- countdictstack dict_count sub { end } repeat
- b4_Inc_state restore
-} bind def
-
-% Check PostScript language level.
-/languagelevel where {
- pop /gs_languagelevel languagelevel def
-} {
- /gs_languagelevel 1 def
-} ifelse
-%%EndResource
-%%BeginResource: procset Enscript-Encoding-88591 1.6 1
-/encoding_vector [
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/space /exclam /quotedbl /numbersign
-/dollar /percent /ampersand /quoteright
-/parenleft /parenright /asterisk /plus
-/comma /hyphen /period /slash
-/zero /one /two /three
-/four /five /six /seven
-/eight /nine /colon /semicolon
-/less /equal /greater /question
-/at /A /B /C
-/D /E /F /G
-/H /I /J /K
-/L /M /N /O
-/P /Q /R /S
-/T /U /V /W
-/X /Y /Z /bracketleft
-/backslash /bracketright /asciicircum /underscore
-/quoteleft /a /b /c
-/d /e /f /g
-/h /i /j /k
-/l /m /n /o
-/p /q /r /s
-/t /u /v /w
-/x /y /z /braceleft
-/bar /braceright /tilde /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/space /exclamdown /cent /sterling
-/currency /yen /brokenbar /section
-/dieresis /copyright /ordfeminine /guillemotleft
-/logicalnot /hyphen /registered /macron
-/degree /plusminus /twosuperior /threesuperior
-/acute /mu /paragraph /bullet
-/cedilla /onesuperior /ordmasculine /guillemotright
-/onequarter /onehalf /threequarters /questiondown
-/Agrave /Aacute /Acircumflex /Atilde
-/Adieresis /Aring /AE /Ccedilla
-/Egrave /Eacute /Ecircumflex /Edieresis
-/Igrave /Iacute /Icircumflex /Idieresis
-/Eth /Ntilde /Ograve /Oacute
-/Ocircumflex /Otilde /Odieresis /multiply
-/Oslash /Ugrave /Uacute /Ucircumflex
-/Udieresis /Yacute /Thorn /germandbls
-/agrave /aacute /acircumflex /atilde
-/adieresis /aring /ae /ccedilla
-/egrave /eacute /ecircumflex /edieresis
-/igrave /iacute /icircumflex /idieresis
-/eth /ntilde /ograve /oacute
-/ocircumflex /otilde /odieresis /divide
-/oslash /ugrave /uacute /ucircumflex
-/udieresis /yacute /thorn /ydieresis
-] def
-%%EndResource
-%%EndProlog
-%%BeginSetup
-%%IncludeResource: font Courier-Bold
-%%IncludeResource: font Courier
-/HFpt_w 10 def
-/HFpt_h 10 def
-/Courier-Bold /HF-gs-font MF
-/HF /HF-gs-font findfont [HFpt_w 0 0 HFpt_h 0 0] makefont def
-/Courier /F-gs-font MF
-/F-gs-font 10 10 SF
-/#copies 1 def
-/d_page_w 520 def
-/d_page_h 747 def
-/d_header_x 0 def
-/d_header_y 747 def
-/d_header_w 520 def
-/d_header_h 0 def
-/d_footer_x 0 def
-/d_footer_y 0 def
-/d_footer_w 520 def
-/d_footer_h 0 def
-/d_output_w 520 def
-/d_output_h 747 def
-/cols 1 def
-userdict/PStoPSxform PStoPSmatrix matrix currentmatrix
- matrix invertmatrix matrix concatmatrix
- matrix invertmatrix put
-%%EndSetup
-%%Page: (0,1) 1
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 1 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 701 M
-(Network Working Group T. Ylonen) s
-5 690 M
-(Internet-Draft S. Lehtinen) s
-5 679 M
-(Expires: April 1, 2002 SSH Communications Security Corp) s
-5 668 M
-( October 2001) s
-5 635 M
-( SSH File Transfer Protocol) s
-5 624 M
-( draft-ietf-secsh-filexfer-02.txt) s
-5 602 M
-(Status of this Memo) s
-5 580 M
-( This document is an Internet-Draft and is in full conformance with) s
-5 569 M
-( all provisions of Section 10 of RFC2026.) s
-5 547 M
-( Internet-Drafts are working documents of the Internet Engineering) s
-5 536 M
-( Task Force \(IETF\), its areas, and its working groups. Note that) s
-5 525 M
-( other groups may also distribute working documents as Internet-) s
-5 514 M
-( Drafts.) s
-5 492 M
-( Internet-Drafts are draft documents valid for a maximum of six months) s
-5 481 M
-( and may be updated, replaced, or obsoleted by other documents at any) s
-5 470 M
-( time. It is inappropriate to use Internet-Drafts as reference) s
-5 459 M
-( material or to cite them other than as "work in progress.") s
-5 437 M
-( The list of current Internet-Drafts can be accessed at http://) s
-5 426 M
-( www.ietf.org/ietf/1id-abstracts.txt.) s
-5 404 M
-( The list of Internet-Draft Shadow Directories can be accessed at) s
-5 393 M
-( http://www.ietf.org/shadow.html.) s
-5 371 M
-( This Internet-Draft will expire on April 1, 2002.) s
-5 349 M
-(Copyright Notice) s
-5 327 M
-( Copyright \(C\) The Internet Society \(2001\). All Rights Reserved.) s
-5 305 M
-(Abstract) s
-5 283 M
-( The SSH File Transfer Protocol provides secure file transfer) s
-5 272 M
-( functionality over any reliable data stream. It is the standard file) s
-5 261 M
-( transfer protocol for use with the SSH2 protocol. This document) s
-5 250 M
-( describes the file transfer protocol and its interface to the SSH2) s
-5 239 M
-( protocol suite.) s
-5 129 M
-(Ylonen & Lehtinen Expires April 1, 2002 [Page 1]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 2 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH File Transfer Protocol October 2001) s
-5 690 M
-(Table of Contents) s
-5 668 M
-( 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3) s
-5 657 M
-( 2. Use with the SSH Connection Protocol . . . . . . . . . . . . 4) s
-5 646 M
-( 3. General Packet Format . . . . . . . . . . . . . . . . . . . 5) s
-5 635 M
-( 4. Protocol Initialization . . . . . . . . . . . . . . . . . . 7) s
-5 624 M
-( 5. File Attributes . . . . . . . . . . . . . . . . . . . . . . 8) s
-5 613 M
-( 6. Requests From the Client to the Server . . . . . . . . . . . 10) s
-5 602 M
-( 6.1 Request Synchronization and Reordering . . . . . . . . . . . 10) s
-5 591 M
-( 6.2 File Names . . . . . . . . . . . . . . . . . . . . . . . . . 11) s
-5 580 M
-( 6.3 Opening, Creating, and Closing Files . . . . . . . . . . . . 11) s
-5 569 M
-( 6.4 Reading and Writing . . . . . . . . . . . . . . . . . . . . 13) s
-5 558 M
-( 6.5 Removing and Renaming Files . . . . . . . . . . . . . . . . 14) s
-5 547 M
-( 6.6 Creating and Deleting Directories . . . . . . . . . . . . . 15) s
-5 536 M
-( 6.7 Scanning Directories . . . . . . . . . . . . . . . . . . . . 15) s
-5 525 M
-( 6.8 Retrieving File Attributes . . . . . . . . . . . . . . . . . 16) s
-5 514 M
-( 6.9 Setting File Attributes . . . . . . . . . . . . . . . . . . 17) s
-5 503 M
-( 6.10 Dealing with Symbolic links . . . . . . . . . . . . . . . . 18) s
-5 492 M
-( 6.11 Canonicalizing the Server-Side Path Name . . . . . . . . . . 18) s
-5 481 M
-( 7. Responses from the Server to the Client . . . . . . . . . . 20) s
-5 470 M
-( 8. Vendor-Specific Extensions . . . . . . . . . . . . . . . . . 24) s
-5 459 M
-( 9. Security Considerations . . . . . . . . . . . . . . . . . . 25) s
-5 448 M
-( 10. Changes from previous protocol versions . . . . . . . . . . 26) s
-5 437 M
-( 10.1 Changes between versions 3 and 2 . . . . . . . . . . . . . . 26) s
-5 426 M
-( 10.2 Changes between versions 2 and 1 . . . . . . . . . . . . . . 26) s
-5 415 M
-( 10.3 Changes between versions 1 and 0 . . . . . . . . . . . . . . 26) s
-5 404 M
-( 11. Trademark Issues . . . . . . . . . . . . . . . . . . . . . . 27) s
-5 393 M
-( References . . . . . . . . . . . . . . . . . . . . . . . . . 28) s
-5 382 M
-( Authors' Addresses . . . . . . . . . . . . . . . . . . . . . 28) s
-5 371 M
-( Full Copyright Statement . . . . . . . . . . . . . . . . . . 29) s
-5 129 M
-(Ylonen & Lehtinen Expires April 1, 2002 [Page 2]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (2,3) 2
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 3 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH File Transfer Protocol October 2001) s
-5 690 M
-(1. Introduction) s
-5 668 M
-( This protocol provides secure file transfer \(and more generally file) s
-5 657 M
-( system access\) functionality over a reliable data stream, such as a) s
-5 646 M
-( channel in the SSH2 protocol [3].) s
-5 624 M
-( This protocol is designed so that it could be used to implement a) s
-5 613 M
-( secure remote file system service, as well as a secure file transfer) s
-5 602 M
-( service.) s
-5 580 M
-( This protocol assumes that it runs over a secure channel, and that) s
-5 569 M
-( the server has already authenticated the user at the client end, and) s
-5 558 M
-( that the identity of the client user is externally available to the) s
-5 547 M
-( server implementation.) s
-5 525 M
-( In general, this protocol follows a simple request-response model.) s
-5 514 M
-( Each request and response contains a sequence number and multiple) s
-5 503 M
-( requests may be pending simultaneously. There are a relatively large) s
-5 492 M
-( number of different request messages, but a small number of possible) s
-5 481 M
-( response messages. Each request has one or more response messages) s
-5 470 M
-( that may be returned in result \(e.g., a read either returns data or) s
-5 459 M
-( reports error status\).) s
-5 437 M
-( The packet format descriptions in this specification follow the) s
-5 426 M
-( notation presented in the secsh architecture draft.[3].) s
-5 404 M
-( Even though this protocol is described in the context of the SSH2) s
-5 393 M
-( protocol, this protocol is general and independent of the rest of the) s
-5 382 M
-( SSH2 protocol suite. It could be used in a number of different) s
-5 371 M
-( applications, such as secure file transfer over TLS RFC 2246 [1] and) s
-5 360 M
-( transfer of management information in VPN applications.) s
-5 129 M
-(Ylonen & Lehtinen Expires April 1, 2002 [Page 3]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 4 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH File Transfer Protocol October 2001) s
-5 690 M
-(2. Use with the SSH Connection Protocol) s
-5 668 M
-( When used with the SSH2 Protocol suite, this protocol is intended to) s
-5 657 M
-( be used from the SSH Connection Protocol [5] as a subsystem, as) s
-5 646 M
-( described in section ``Starting a Shell or a Command''. The) s
-5 635 M
-( subsystem name used with this protocol is "sftp".) s
-5 129 M
-(Ylonen & Lehtinen Expires April 1, 2002 [Page 4]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (4,5) 3
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 5 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH File Transfer Protocol October 2001) s
-5 690 M
-(3. General Packet Format) s
-5 668 M
-( All packets transmitted over the secure connection are of the) s
-5 657 M
-( following format:) s
-5 635 M
-( uint32 length) s
-5 624 M
-( byte type) s
-5 613 M
-( byte[length - 1] data payload) s
-5 591 M
-( That is, they are just data preceded by 32-bit length and 8-bit type) s
-5 580 M
-( fields. The `length' is the length of the data area, and does not) s
-5 569 M
-( include the `length' field itself. The format and interpretation of) s
-5 558 M
-( the data area depends on the packet type.) s
-5 536 M
-( All packet descriptions below only specify the packet type and the) s
-5 525 M
-( data that goes into the data field. Thus, they should be prefixed by) s
-5 514 M
-( the `length' and `type' fields.) s
-5 492 M
-( The maximum size of a packet is in practice determined by the client) s
-5 481 M
-( \(the maximum size of read or write requests that it sends, plus a few) s
-5 470 M
-( bytes of packet overhead\). All servers SHOULD support packets of at) s
-5 459 M
-( least 34000 bytes \(where the packet size refers to the full length,) s
-5 448 M
-( including the header above\). This should allow for reads and writes) s
-5 437 M
-( of at most 32768 bytes.) s
-5 415 M
-( There is no limit on the number of outstanding \(non-acknowledged\)) s
-5 404 M
-( requests that the client may send to the server. In practice this is) s
-5 393 M
-( limited by the buffering available on the data stream and the queuing) s
-5 382 M
-( performed by the server. If the server's queues are full, it should) s
-5 371 M
-( not read any more data from the stream, and flow control will prevent) s
-5 360 M
-( the client from sending more requests. Note, however, that while) s
-5 349 M
-( there is no restriction on the protocol level, the client's API may) s
-5 338 M
-( provide a limit in order to prevent infinite queuing of outgoing) s
-5 327 M
-( requests at the client.) s
-5 129 M
-(Ylonen & Lehtinen Expires April 1, 2002 [Page 5]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 6 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH File Transfer Protocol October 2001) s
-5 690 M
-( The following values are defined for packet types.) s
-5 668 M
-( #define SSH_FXP_INIT 1) s
-5 657 M
-( #define SSH_FXP_VERSION 2) s
-5 646 M
-( #define SSH_FXP_OPEN 3) s
-5 635 M
-( #define SSH_FXP_CLOSE 4) s
-5 624 M
-( #define SSH_FXP_READ 5) s
-5 613 M
-( #define SSH_FXP_WRITE 6) s
-5 602 M
-( #define SSH_FXP_LSTAT 7) s
-5 591 M
-( #define SSH_FXP_FSTAT 8) s
-5 580 M
-( #define SSH_FXP_SETSTAT 9) s
-5 569 M
-( #define SSH_FXP_FSETSTAT 10) s
-5 558 M
-( #define SSH_FXP_OPENDIR 11) s
-5 547 M
-( #define SSH_FXP_READDIR 12) s
-5 536 M
-( #define SSH_FXP_REMOVE 13) s
-5 525 M
-( #define SSH_FXP_MKDIR 14) s
-5 514 M
-( #define SSH_FXP_RMDIR 15) s
-5 503 M
-( #define SSH_FXP_REALPATH 16) s
-5 492 M
-( #define SSH_FXP_STAT 17) s
-5 481 M
-( #define SSH_FXP_RENAME 18) s
-5 470 M
-( #define SSH_FXP_READLINK 19) s
-5 459 M
-( #define SSH_FXP_SYMLINK 20) s
-5 448 M
-( #define SSH_FXP_STATUS 101) s
-5 437 M
-( #define SSH_FXP_HANDLE 102) s
-5 426 M
-( #define SSH_FXP_DATA 103) s
-5 415 M
-( #define SSH_FXP_NAME 104) s
-5 404 M
-( #define SSH_FXP_ATTRS 105) s
-5 393 M
-( #define SSH_FXP_EXTENDED 200) s
-5 382 M
-( #define SSH_FXP_EXTENDED_REPLY 201) s
-5 360 M
-( Additional packet types should only be defined if the protocol) s
-5 349 M
-( version number \(see Section ``Protocol Initialization''\) is) s
-5 338 M
-( incremented, and their use MUST be negotiated using the version) s
-5 327 M
-( number. However, the SSH_FXP_EXTENDED and SSH_FXP_EXTENDED_REPLY) s
-5 316 M
-( packets can be used to implement vendor-specific extensions. See) s
-5 305 M
-( Section ``Vendor-Specific-Extensions'' for more details.) s
-5 129 M
-(Ylonen & Lehtinen Expires April 1, 2002 [Page 6]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (6,7) 4
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 7 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH File Transfer Protocol October 2001) s
-5 690 M
-(4. Protocol Initialization) s
-5 668 M
-( When the file transfer protocol starts, it first sends a SSH_FXP_INIT) s
-5 657 M
-( \(including its version number\) packet to the server. The server) s
-5 646 M
-( responds with a SSH_FXP_VERSION packet, supplying the lowest of its) s
-5 635 M
-( own and the client's version number. Both parties should from then) s
-5 624 M
-( on adhere to particular version of the protocol.) s
-5 602 M
-( The SSH_FXP_INIT packet \(from client to server\) has the following) s
-5 591 M
-( data:) s
-5 569 M
-( uint32 version) s
-5 558 M
-( <extension data>) s
-5 536 M
-( The SSH_FXP_VERSION packet \(from server to client\) has the following) s
-5 525 M
-( data:) s
-5 503 M
-( uint32 version) s
-5 492 M
-( <extension data>) s
-5 470 M
-( The version number of the protocol specified in this document is 3.) s
-5 459 M
-( The version number should be incremented for each incompatible) s
-5 448 M
-( revision of this protocol.) s
-5 426 M
-( The extension data in the above packets may be empty, or may be a) s
-5 415 M
-( sequence of) s
-5 393 M
-( string extension_name) s
-5 382 M
-( string extension_data) s
-5 360 M
-( pairs \(both strings MUST always be present if one is, but the) s
-5 349 M
-( `extension_data' string may be of zero length\). If present, these) s
-5 338 M
-( strings indicate extensions to the baseline protocol. The) s
-5 327 M
-( `extension_name' field\(s\) identify the name of the extension. The) s
-5 316 M
-( name should be of the form "name@domain", where the domain is the DNS) s
-5 305 M
-( domain name of the organization defining the extension. Additional) s
-5 294 M
-( names that are not of this format may be defined later by the IETF.) s
-5 283 M
-( Implementations MUST silently ignore any extensions whose name they) s
-5 272 M
-( do not recognize.) s
-5 129 M
-(Ylonen & Lehtinen Expires April 1, 2002 [Page 7]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 8 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH File Transfer Protocol October 2001) s
-5 690 M
-(5. File Attributes) s
-5 668 M
-( A new compound data type is defined for encoding file attributes. It) s
-5 657 M
-( is basically just a combination of elementary types, but is defined) s
-5 646 M
-( once because of the non-trivial description of the fields and to) s
-5 635 M
-( ensure maintainability.) s
-5 613 M
-( The same encoding is used both when returning file attributes from) s
-5 602 M
-( the server and when sending file attributes to the server. When) s
-5 591 M
-( sending it to the server, the flags field specifies which attributes) s
-5 580 M
-( are included, and the server will use default values for the) s
-5 569 M
-( remaining attributes \(or will not modify the values of remaining) s
-5 558 M
-( attributes\). When receiving attributes from the server, the flags) s
-5 547 M
-( specify which attributes are included in the returned data. The) s
-5 536 M
-( server normally returns all attributes it knows about.) s
-5 514 M
-( uint32 flags) s
-5 503 M
-( uint64 size present only if flag SSH_FILEXFER_ATTR_SIZE) s
-5 492 M
-( uint32 uid present only if flag SSH_FILEXFER_ATTR_UIDGID) s
-5 481 M
-( uint32 gid present only if flag SSH_FILEXFER_ATTR_UIDGID) s
-5 470 M
-( uint32 permissions present only if flag SSH_FILEXFER_ATTR_PERMISSIONS) s
-5 459 M
-( uint32 atime present only if flag SSH_FILEXFER_ACMODTIME) s
-5 448 M
-( uint32 mtime present only if flag SSH_FILEXFER_ACMODTIME) s
-5 437 M
-( uint32 extended_count present only if flag SSH_FILEXFER_ATTR_EXTENDED) s
-5 426 M
-( string extended_type) s
-5 415 M
-( string extended_data) s
-5 404 M
-( ... more extended data \(extended_type - extended_data pairs\),) s
-5 393 M
-( so that number of pairs equals extended_count) s
-5 371 M
-( The `flags' specify which of the fields are present. Those fields) s
-5 360 M
-( for which the corresponding flag is not set are not present \(not) s
-5 349 M
-( included in the packet\). New flags can only be added by incrementing) s
-5 338 M
-( the protocol version number \(or by using the extension mechanism) s
-5 327 M
-( described below\).) s
-5 305 M
-( The `size' field specifies the size of the file in bytes.) s
-5 283 M
-( The `uid' and `gid' fields contain numeric Unix-like user and group) s
-5 272 M
-( identifiers, respectively.) s
-5 250 M
-( The `permissions' field contains a bit mask of file permissions as) s
-5 239 M
-( defined by posix [1].) s
-5 217 M
-( The `atime' and `mtime' contain the access and modification times of) s
-5 206 M
-( the files, respectively. They are represented as seconds from Jan 1,) s
-5 195 M
-( 1970 in UTC.) s
-5 173 M
-( The SSH_FILEXFER_ATTR_EXTENDED flag provides a general extension) s
-5 129 M
-(Ylonen & Lehtinen Expires April 1, 2002 [Page 8]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (8,9) 5
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 9 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH File Transfer Protocol October 2001) s
-5 690 M
-( mechanism for vendor-specific extensions. If the flag is specified,) s
-5 679 M
-( then the `extended_count' field is present. It specifies the number) s
-5 668 M
-( of extended_type-extended_data pairs that follow. Each of these) s
-5 657 M
-( pairs specifies an extended attribute. For each of the attributes,) s
-5 646 M
-( the extended_type field should be a string of the format) s
-5 635 M
-( "name@domain", where "domain" is a valid, registered domain name and) s
-5 624 M
-( "name" identifies the method. The IETF may later standardize certain) s
-5 613 M
-( names that deviate from this format \(e.g., that do not contain the) s
-5 602 M
-( "@" sign\). The interpretation of `extended_data' depends on the) s
-5 591 M
-( type. Implementations SHOULD ignore extended data fields that they) s
-5 580 M
-( do not understand.) s
-5 558 M
-( Additional fields can be added to the attributes by either defining) s
-5 547 M
-( additional bits to the flags field to indicate their presence, or by) s
-5 536 M
-( defining extended attributes for them. The extended attributes) s
-5 525 M
-( mechanism is recommended for most purposes; additional flags bits) s
-5 514 M
-( should only be defined by an IETF standards action that also) s
-5 503 M
-( increments the protocol version number. The use of such new fields) s
-5 492 M
-( MUST be negotiated by the version number in the protocol exchange.) s
-5 481 M
-( It is a protocol error if a packet with unsupported protocol bits is) s
-5 470 M
-( received.) s
-5 448 M
-( The flags bits are defined to have the following values:) s
-5 426 M
-( #define SSH_FILEXFER_ATTR_SIZE 0x00000001) s
-5 415 M
-( #define SSH_FILEXFER_ATTR_UIDGID 0x00000002) s
-5 404 M
-( #define SSH_FILEXFER_ATTR_PERMISSIONS 0x00000004) s
-5 393 M
-( #define SSH_FILEXFER_ATTR_ACMODTIME 0x00000008) s
-5 382 M
-( #define SSH_FILEXFER_ATTR_EXTENDED 0x80000000) s
-5 129 M
-(Ylonen & Lehtinen Expires April 1, 2002 [Page 9]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 10 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH File Transfer Protocol October 2001) s
-5 690 M
-(6. Requests From the Client to the Server) s
-5 668 M
-( Requests from the client to the server represent the various file) s
-5 657 M
-( system operations. Each request begins with an `id' field, which is) s
-5 646 M
-( a 32-bit identifier identifying the request \(selected by the client\).) s
-5 635 M
-( The same identifier will be returned in the response to the request.) s
-5 624 M
-( One possible implementation of it is a monotonically increasing) s
-5 613 M
-( request sequence number \(modulo 2^32\).) s
-5 591 M
-( Many operations in the protocol operate on open files. The) s
-5 580 M
-( SSH_FXP_OPEN request can return a file handle \(which is an opaque) s
-5 569 M
-( variable-length string\) which may be used to access the file later) s
-5 558 M
-( \(e.g. in a read operation\). The client MUST NOT send requests the) s
-5 547 M
-( server with bogus or closed handles. However, the server MUST) s
-5 536 M
-( perform adequate checks on the handle in order to avoid security) s
-5 525 M
-( risks due to fabricated handles.) s
-5 503 M
-( This design allows either stateful and stateless server) s
-5 492 M
-( implementation, as well as an implementation which caches state) s
-5 481 M
-( between requests but may also flush it. The contents of the file) s
-5 470 M
-( handle string are entirely up to the server and its design. The) s
-5 459 M
-( client should not modify or attempt to interpret the file handle) s
-5 448 M
-( strings.) s
-5 426 M
-( The file handle strings MUST NOT be longer than 256 bytes.) s
-5 404 M
-(6.1 Request Synchronization and Reordering) s
-5 382 M
-( The protocol and implementations MUST process requests relating to) s
-5 371 M
-( the same file in the order in which they are received. In other) s
-5 360 M
-( words, if an application submits multiple requests to the server, the) s
-5 349 M
-( results in the responses will be the same as if it had sent the) s
-5 338 M
-( requests one at a time and waited for the response in each case. For) s
-5 327 M
-( example, the server may process non-overlapping read/write requests) s
-5 316 M
-( to the same file in parallel, but overlapping reads and writes cannot) s
-5 305 M
-( be reordered or parallelized. However, there are no ordering) s
-5 294 M
-( restrictions on the server for processing requests from two different) s
-5 283 M
-( file transfer connections. The server may interleave and parallelize) s
-5 272 M
-( them at will.) s
-5 250 M
-( There are no restrictions on the order in which responses to) s
-5 239 M
-( outstanding requests are delivered to the client, except that the) s
-5 228 M
-( server must ensure fairness in the sense that processing of no) s
-5 217 M
-( request will be indefinitely delayed even if the client is sending) s
-5 206 M
-( other requests so that there are multiple outstanding requests all) s
-5 195 M
-( the time.) s
-5 129 M
-(Ylonen & Lehtinen Expires April 1, 2002 [Page 10]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (10,11) 6
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 11 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH File Transfer Protocol October 2001) s
-5 690 M
-(6.2 File Names) s
-5 668 M
-( This protocol represents file names as strings. File names are) s
-5 657 M
-( assumed to use the slash \('/'\) character as a directory separator.) s
-5 635 M
-( File names starting with a slash are "absolute", and are relative to) s
-5 624 M
-( the root of the file system. Names starting with any other character) s
-5 613 M
-( are relative to the user's default directory \(home directory\). Note) s
-5 602 M
-( that identifying the user is assumed to take place outside of this) s
-5 591 M
-( protocol.) s
-5 569 M
-( Servers SHOULD interpret a path name component ".." as referring to) s
-5 558 M
-( the parent directory, and "." as referring to the current directory.) s
-5 547 M
-( If the server implementation limits access to certain parts of the) s
-5 536 M
-( file system, it must be extra careful in parsing file names when) s
-5 525 M
-( enforcing such restrictions. There have been numerous reported) s
-5 514 M
-( security bugs where a ".." in a path name has allowed access outside) s
-5 503 M
-( the intended area.) s
-5 481 M
-( An empty path name is valid, and it refers to the user's default) s
-5 470 M
-( directory \(usually the user's home directory\).) s
-5 448 M
-( Otherwise, no syntax is defined for file names by this specification.) s
-5 437 M
-( Clients should not make any other assumptions; however, they can) s
-5 426 M
-( splice path name components returned by SSH_FXP_READDIR together) s
-5 415 M
-( using a slash \('/'\) as the separator, and that will work as expected.) s
-5 393 M
-( It is understood that the lack of well-defined semantics for file) s
-5 382 M
-( names may cause interoperability problems between clients and servers) s
-5 371 M
-( using radically different operating systems. However, this approach) s
-5 360 M
-( is known to work acceptably with most systems, and alternative) s
-5 349 M
-( approaches that e.g. treat file names as sequences of structured) s
-5 338 M
-( components are quite complicated.) s
-5 316 M
-(6.3 Opening, Creating, and Closing Files) s
-5 294 M
-( Files are opened and created using the SSH_FXP_OPEN message, whose) s
-5 283 M
-( data part is as follows:) s
-5 261 M
-( uint32 id) s
-5 250 M
-( string filename) s
-5 239 M
-( uint32 pflags) s
-5 228 M
-( ATTRS attrs) s
-5 206 M
-( The `id' field is the request identifier as for all requests.) s
-5 184 M
-( The `filename' field specifies the file name. See Section ``File) s
-5 173 M
-( Names'' for more information.) s
-5 129 M
-(Ylonen & Lehtinen Expires April 1, 2002 [Page 11]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 12 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH File Transfer Protocol October 2001) s
-5 690 M
-( The `pflags' field is a bitmask. The following bits have been) s
-5 679 M
-( defined.) s
-5 657 M
-( #define SSH_FXF_READ 0x00000001) s
-5 646 M
-( #define SSH_FXF_WRITE 0x00000002) s
-5 635 M
-( #define SSH_FXF_APPEND 0x00000004) s
-5 624 M
-( #define SSH_FXF_CREAT 0x00000008) s
-5 613 M
-( #define SSH_FXF_TRUNC 0x00000010) s
-5 602 M
-( #define SSH_FXF_EXCL 0x00000020) s
-5 580 M
-( These have the following meanings:) s
-5 558 M
-( SSH_FXF_READ) s
-5 547 M
-( Open the file for reading.) s
-5 525 M
-( SSH_FXF_WRITE) s
-5 514 M
-( Open the file for writing. If both this and SSH_FXF_READ are) s
-5 503 M
-( specified, the file is opened for both reading and writing.) s
-5 481 M
-( SSH_FXF_APPEND) s
-5 470 M
-( Force all writes to append data at the end of the file.) s
-5 448 M
-( SSH_FXF_CREAT) s
-5 437 M
-( If this flag is specified, then a new file will be created if one) s
-5 426 M
-( does not already exist \(if O_TRUNC is specified, the new file will) s
-5 415 M
-( be truncated to zero length if it previously exists\).) s
-5 393 M
-( SSH_FXF_TRUNC) s
-5 382 M
-( Forces an existing file with the same name to be truncated to zero) s
-5 371 M
-( length when creating a file by specifying SSH_FXF_CREAT.) s
-5 360 M
-( SSH_FXF_CREAT MUST also be specified if this flag is used.) s
-5 338 M
-( SSH_FXF_EXCL) s
-5 327 M
-( Causes the request to fail if the named file already exists.) s
-5 316 M
-( SSH_FXF_CREAT MUST also be specified if this flag is used.) s
-5 294 M
-( The `attrs' field specifies the initial attributes for the file.) s
-5 283 M
-( Default values will be used for those attributes that are not) s
-5 272 M
-( specified. See Section ``File Attributes'' for more information.) s
-5 250 M
-( Regardless the server operating system, the file will always be) s
-5 239 M
-( opened in "binary" mode \(i.e., no translations between different) s
-5 228 M
-( character sets and newline encodings\).) s
-5 206 M
-( The response to this message will be either SSH_FXP_HANDLE \(if the) s
-5 195 M
-( operation is successful\) or SSH_FXP_STATUS \(if the operation fails\).) s
-5 129 M
-(Ylonen & Lehtinen Expires April 1, 2002 [Page 12]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (12,13) 7
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 13 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH File Transfer Protocol October 2001) s
-5 690 M
-( A file is closed by using the SSH_FXP_CLOSE request. Its data field) s
-5 679 M
-( has the following format:) s
-5 657 M
-( uint32 id) s
-5 646 M
-( string handle) s
-5 624 M
-( where `id' is the request identifier, and `handle' is a handle) s
-5 613 M
-( previously returned in the response to SSH_FXP_OPEN or) s
-5 602 M
-( SSH_FXP_OPENDIR. The handle becomes invalid immediately after this) s
-5 591 M
-( request has been sent.) s
-5 569 M
-( The response to this request will be a SSH_FXP_STATUS message. One) s
-5 558 M
-( should note that on some server platforms even a close can fail.) s
-5 547 M
-( This can happen e.g. if the server operating system caches writes,) s
-5 536 M
-( and an error occurs while flushing cached writes during the close.) s
-5 514 M
-(6.4 Reading and Writing) s
-5 492 M
-( Once a file has been opened, it can be read using the SSH_FXP_READ) s
-5 481 M
-( message, which has the following format:) s
-5 459 M
-( uint32 id) s
-5 448 M
-( string handle) s
-5 437 M
-( uint64 offset) s
-5 426 M
-( uint32 len) s
-5 404 M
-( where `id' is the request identifier, `handle' is an open file handle) s
-5 393 M
-( returned by SSH_FXP_OPEN, `offset' is the offset \(in bytes\) relative) s
-5 382 M
-( to the beginning of the file from where to start reading, and `len') s
-5 371 M
-( is the maximum number of bytes to read.) s
-5 349 M
-( In response to this request, the server will read as many bytes as it) s
-5 338 M
-( can from the file \(up to `len'\), and return them in a SSH_FXP_DATA) s
-5 327 M
-( message. If an error occurs or EOF is encountered before reading any) s
-5 316 M
-( data, the server will respond with SSH_FXP_STATUS. For normal disk) s
-5 305 M
-( files, it is guaranteed that this will read the specified number of) s
-5 294 M
-( bytes, or up to end of file. For e.g. device files this may return) s
-5 283 M
-( fewer bytes than requested.) s
-5 261 M
-( Writing to a file is achieved using the SSH_FXP_WRITE message, which) s
-5 250 M
-( has the following format:) s
-5 228 M
-( uint32 id) s
-5 217 M
-( string handle) s
-5 206 M
-( uint64 offset) s
-5 195 M
-( string data) s
-5 173 M
-( where `id' is a request identifier, `handle' is a file handle) s
-5 129 M
-(Ylonen & Lehtinen Expires April 1, 2002 [Page 13]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 14 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH File Transfer Protocol October 2001) s
-5 690 M
-( returned by SSH_FXP_OPEN, `offset' is the offset \(in bytes\) from the) s
-5 679 M
-( beginning of the file where to start writing, and `data' is the data) s
-5 668 M
-( to be written.) s
-5 646 M
-( The write will extend the file if writing beyond the end of the file.) s
-5 635 M
-( It is legal to write way beyond the end of the file; the semantics) s
-5 624 M
-( are to write zeroes from the end of the file to the specified offset) s
-5 613 M
-( and then the data. On most operating systems, such writes do not) s
-5 602 M
-( allocate disk space but instead leave "holes" in the file.) s
-5 580 M
-( The server responds to a write request with a SSH_FXP_STATUS message.) s
-5 558 M
-(6.5 Removing and Renaming Files) s
-5 536 M
-( Files can be removed using the SSH_FXP_REMOVE message. It has the) s
-5 525 M
-( following format:) s
-5 503 M
-( uint32 id) s
-5 492 M
-( string filename) s
-5 470 M
-( where `id' is the request identifier and `filename' is the name of) s
-5 459 M
-( the file to be removed. See Section ``File Names'' for more) s
-5 448 M
-( information. This request cannot be used to remove directories.) s
-5 426 M
-( The server will respond to this request with a SSH_FXP_STATUS) s
-5 415 M
-( message.) s
-5 393 M
-( Files \(and directories\) can be renamed using the SSH_FXP_RENAME) s
-5 382 M
-( message. Its data is as follows:) s
-5 360 M
-( uint32 id) s
-5 349 M
-( string oldpath) s
-5 338 M
-( string newpath) s
-5 316 M
-( where `id' is the request identifier, `oldpath' is the name of an) s
-5 305 M
-( existing file or directory, and `newpath' is the new name for the) s
-5 294 M
-( file or directory. It is an error if there already exists a file) s
-5 283 M
-( with the name specified by newpath. The server may also fail rename) s
-5 272 M
-( requests in other situations, for example if `oldpath' and `newpath') s
-5 261 M
-( point to different file systems on the server.) s
-5 239 M
-( The server will respond to this request with a SSH_FXP_STATUS) s
-5 228 M
-( message.) s
-5 129 M
-(Ylonen & Lehtinen Expires April 1, 2002 [Page 14]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (14,15) 8
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 15 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH File Transfer Protocol October 2001) s
-5 690 M
-(6.6 Creating and Deleting Directories) s
-5 668 M
-( New directories can be created using the SSH_FXP_MKDIR request. It) s
-5 657 M
-( has the following format:) s
-5 635 M
-( uint32 id) s
-5 624 M
-( string path) s
-5 613 M
-( ATTRS attrs) s
-5 591 M
-( where `id' is the request identifier, `path' and `attrs' specifies) s
-5 580 M
-( the modifications to be made to its attributes. See Section ``File) s
-5 569 M
-( Names'' for more information on file names. Attributes are discussed) s
-5 558 M
-( in more detail in Section ``File Attributes''. specifies the) s
-5 547 M
-( directory to be created. An error will be returned if a file or) s
-5 536 M
-( directory with the specified path already exists. The server will) s
-5 525 M
-( respond to this request with a SSH_FXP_STATUS message.) s
-5 503 M
-( Directories can be removed using the SSH_FXP_RMDIR request, which) s
-5 492 M
-( has the following format:) s
-5 470 M
-( uint32 id) s
-5 459 M
-( string path) s
-5 437 M
-( where `id' is the request identifier, and `path' specifies the) s
-5 426 M
-( directory to be removed. See Section ``File Names'' for more) s
-5 415 M
-( information on file names. An error will be returned if no directory) s
-5 404 M
-( with the specified path exists, or if the specified directory is not) s
-5 393 M
-( empty, or if the path specified a file system object other than a) s
-5 382 M
-( directory. The server responds to this request with a SSH_FXP_STATUS) s
-5 371 M
-( message.) s
-5 349 M
-(6.7 Scanning Directories) s
-5 327 M
-( The files in a directory can be listed using the SSH_FXP_OPENDIR and) s
-5 316 M
-( SSH_FXP_READDIR requests. Each SSH_FXP_READDIR request returns one) s
-5 305 M
-( or more file names with full file attributes for each file. The) s
-5 294 M
-( client should call SSH_FXP_READDIR repeatedly until it has found the) s
-5 283 M
-( file it is looking for or until the server responds with a) s
-5 272 M
-( SSH_FXP_STATUS message indicating an error \(normally SSH_FX_EOF if) s
-5 261 M
-( there are no more files in the directory\). The client should then) s
-5 250 M
-( close the handle using the SSH_FXP_CLOSE request.) s
-5 129 M
-(Ylonen & Lehtinen Expires April 1, 2002 [Page 15]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 16 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH File Transfer Protocol October 2001) s
-5 690 M
-( The SSH_FXP_OPENDIR opens a directory for reading. It has the) s
-5 679 M
-( following format:) s
-5 657 M
-( uint32 id) s
-5 646 M
-( string path) s
-5 624 M
-( where `id' is the request identifier and `path' is the path name of) s
-5 613 M
-( the directory to be listed \(without any trailing slash\). See Section) s
-5 602 M
-( ``File Names'' for more information on file names. This will return) s
-5 591 M
-( an error if the path does not specify a directory or if the directory) s
-5 580 M
-( is not readable. The server will respond to this request with either) s
-5 569 M
-( a SSH_FXP_HANDLE or a SSH_FXP_STATUS message.) s
-5 547 M
-( Once the directory has been successfully opened, files \(and) s
-5 536 M
-( directories\) contained in it can be listed using SSH_FXP_READDIR) s
-5 525 M
-( requests. These are of the format) s
-5 503 M
-( uint32 id) s
-5 492 M
-( string handle) s
-5 470 M
-( where `id' is the request identifier, and `handle' is a handle) s
-5 459 M
-( returned by SSH_FXP_OPENDIR. \(It is a protocol error to attempt to) s
-5 448 M
-( use an ordinary file handle returned by SSH_FXP_OPEN.\)) s
-5 426 M
-( The server responds to this request with either a SSH_FXP_NAME or a) s
-5 415 M
-( SSH_FXP_STATUS message. One or more names may be returned at a time.) s
-5 404 M
-( Full status information is returned for each name in order to speed) s
-5 393 M
-( up typical directory listings.) s
-5 371 M
-( When the client no longer wishes to read more names from the) s
-5 360 M
-( directory, it SHOULD call SSH_FXP_CLOSE for the handle. The handle) s
-5 349 M
-( should be closed regardless of whether an error has occurred or not.) s
-5 327 M
-(6.8 Retrieving File Attributes) s
-5 305 M
-( Very often, file attributes are automatically returned by) s
-5 294 M
-( SSH_FXP_READDIR. However, sometimes there is need to specifically) s
-5 283 M
-( retrieve the attributes for a named file. This can be done using the) s
-5 272 M
-( SSH_FXP_STAT, SSH_FXP_LSTAT and SSH_FXP_FSTAT requests.) s
-5 250 M
-( SSH_FXP_STAT and SSH_FXP_LSTAT only differ in that SSH_FXP_STAT) s
-5 239 M
-( follows symbolic links on the server, whereas SSH_FXP_LSTAT does not) s
-5 228 M
-( follow symbolic links. Both have the same format:) s
-5 206 M
-( uint32 id) s
-5 195 M
-( string path) s
-5 173 M
-( where `id' is the request identifier, and `path' specifies the file) s
-5 129 M
-(Ylonen & Lehtinen Expires April 1, 2002 [Page 16]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (16,17) 9
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 17 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH File Transfer Protocol October 2001) s
-5 690 M
-( system object for which status is to be returned. The server) s
-5 679 M
-( responds to this request with either SSH_FXP_ATTRS or SSH_FXP_STATUS.) s
-5 657 M
-( SSH_FXP_FSTAT differs from the others in that it returns status) s
-5 646 M
-( information for an open file \(identified by the file handle\). Its) s
-5 635 M
-( format is as follows:) s
-5 613 M
-( uint32 id) s
-5 602 M
-( string handle) s
-5 580 M
-( where `id' is the request identifier and `handle' is a file handle) s
-5 569 M
-( returned by SSH_FXP_OPEN. The server responds to this request with) s
-5 558 M
-( SSH_FXP_ATTRS or SSH_FXP_STATUS.) s
-5 536 M
-(6.9 Setting File Attributes) s
-5 514 M
-( File attributes may be modified using the SSH_FXP_SETSTAT and) s
-5 503 M
-( SSH_FXP_FSETSTAT requests. These requests are used for operations) s
-5 492 M
-( such as changing the ownership, permissions or access times, as well) s
-5 481 M
-( as for truncating a file.) s
-5 459 M
-( The SSH_FXP_SETSTAT request is of the following format:) s
-5 437 M
-( uint32 id) s
-5 426 M
-( string path) s
-5 415 M
-( ATTRS attrs) s
-5 393 M
-( where `id' is the request identifier, `path' specifies the file) s
-5 382 M
-( system object \(e.g. file or directory\) whose attributes are to be) s
-5 371 M
-( modified, and `attrs' specifies the modifications to be made to its) s
-5 360 M
-( attributes. Attributes are discussed in more detail in Section) s
-5 349 M
-( ``File Attributes''.) s
-5 327 M
-( An error will be returned if the specified file system object does) s
-5 316 M
-( not exist or the user does not have sufficient rights to modify the) s
-5 305 M
-( specified attributes. The server responds to this request with a) s
-5 294 M
-( SSH_FXP_STATUS message.) s
-5 272 M
-( The SSH_FXP_FSETSTAT request modifies the attributes of a file which) s
-5 261 M
-( is already open. It has the following format:) s
-5 239 M
-( uint32 id) s
-5 228 M
-( string handle) s
-5 217 M
-( ATTRS attrs) s
-5 195 M
-( where `id' is the request identifier, `handle' \(MUST be returned by) s
-5 184 M
-( SSH_FXP_OPEN\) identifies the file whose attributes are to be) s
-5 173 M
-( modified, and `attrs' specifies the modifications to be made to its) s
-5 129 M
-(Ylonen & Lehtinen Expires April 1, 2002 [Page 17]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 18 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH File Transfer Protocol October 2001) s
-5 690 M
-( attributes. Attributes are discussed in more detail in Section) s
-5 679 M
-( ``File Attributes''. The server will respond to this request with) s
-5 668 M
-( SSH_FXP_STATUS.) s
-5 646 M
-(6.10 Dealing with Symbolic links) s
-5 624 M
-( The SSH_FXP_READLINK request may be used to read the target of a) s
-5 613 M
-( symbolic link. It would have a data part as follows:) s
-5 591 M
-( uint32 id) s
-5 580 M
-( string path) s
-5 558 M
-( where `id' is the request identifier and `path' specifies the path) s
-5 547 M
-( name of the symlink to be read.) s
-5 525 M
-( The server will respond with a SSH_FXP_NAME packet containing only) s
-5 514 M
-( one name and a dummy attributes value. The name in the returned) s
-5 503 M
-( packet contains the target of the link. If an error occurs, the) s
-5 492 M
-( server may respond with SSH_FXP_STATUS.) s
-5 470 M
-( The SSH_FXP_SYMLINK request will create a symbolic link on the) s
-5 459 M
-( server. It is of the following format) s
-5 437 M
-( uint32 id) s
-5 426 M
-( string linkpath) s
-5 415 M
-( string targetpath) s
-5 393 M
-( where `id' is the request identifier, `linkpath' specifies the path) s
-5 382 M
-( name of the symlink to be created and `targetpath' specifies the) s
-5 371 M
-( target of the symlink. The server shall respond with a) s
-5 360 M
-( SSH_FXP_STATUS indicating either success \(SSH_FX_OK\) or an error) s
-5 349 M
-( condition.) s
-5 327 M
-(6.11 Canonicalizing the Server-Side Path Name) s
-5 305 M
-( The SSH_FXP_REALPATH request can be used to have the server) s
-5 294 M
-( canonicalize any given path name to an absolute path. This is useful) s
-5 283 M
-( for converting path names containing ".." components or relative) s
-5 272 M
-( pathnames without a leading slash into absolute paths. The format of) s
-5 261 M
-( the request is as follows:) s
-5 239 M
-( uint32 id) s
-5 228 M
-( string path) s
-5 206 M
-( where `id' is the request identifier and `path' specifies the path) s
-5 195 M
-( name to be canonicalized. The server will respond with a) s
-5 184 M
-( SSH_FXP_NAME packet containing only one name and a dummy attributes) s
-5 173 M
-( value. The name is the returned packet will be in canonical form.) s
-5 129 M
-(Ylonen & Lehtinen Expires April 1, 2002 [Page 18]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (18,19) 10
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 19 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH File Transfer Protocol October 2001) s
-5 690 M
-( If an error occurs, the server may also respond with SSH_FXP_STATUS.) s
-5 129 M
-(Ylonen & Lehtinen Expires April 1, 2002 [Page 19]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 20 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH File Transfer Protocol October 2001) s
-5 690 M
-(7. Responses from the Server to the Client) s
-5 668 M
-( The server responds to the client using one of a few response) s
-5 657 M
-( packets. All requests can return a SSH_FXP_STATUS response upon) s
-5 646 M
-( failure. When the operation is successful, any of the responses may) s
-5 635 M
-( be returned \(depending on the operation\). If no data needs to be) s
-5 624 M
-( returned to the client, the SSH_FXP_STATUS response with SSH_FX_OK) s
-5 613 M
-( status is appropriate. Otherwise, the SSH_FXP_HANDLE message is used) s
-5 602 M
-( to return a file handle \(for SSH_FXP_OPEN and SSH_FXP_OPENDIR) s
-5 591 M
-( requests\), SSH_FXP_DATA is used to return data from SSH_FXP_READ,) s
-5 580 M
-( SSH_FXP_NAME is used to return one or more file names from a) s
-5 569 M
-( SSH_FXP_READDIR or SSH_FXP_REALPATH request, and SSH_FXP_ATTRS is) s
-5 558 M
-( used to return file attributes from SSH_FXP_STAT, SSH_FXP_LSTAT, and) s
-5 547 M
-( SSH_FXP_FSTAT requests.) s
-5 525 M
-( Exactly one response will be returned for each request. Each) s
-5 514 M
-( response packet contains a request identifier which can be used to) s
-5 503 M
-( match each response with the corresponding request. Note that it is) s
-5 492 M
-( legal to have several requests outstanding simultaneously, and the) s
-5 481 M
-( server is allowed to send responses to them in a different order from) s
-5 470 M
-( the order in which the requests were sent \(the result of their) s
-5 459 M
-( execution, however, is guaranteed to be as if they had been processed) s
-5 448 M
-( one at a time in the order in which the requests were sent\).) s
-5 426 M
-( Response packets are of the same general format as request packets.) s
-5 415 M
-( Each response packet begins with the request identifier.) s
-5 393 M
-( The format of the data portion of the SSH_FXP_STATUS response is as) s
-5 382 M
-( follows:) s
-5 360 M
-( uint32 id) s
-5 349 M
-( uint32 error/status code) s
-5 338 M
-( string error message \(ISO-10646 UTF-8 [RFC-2279]\)) s
-5 327 M
-( string language tag \(as defined in [RFC-1766]\)) s
-5 305 M
-( where `id' is the request identifier, and `error/status code') s
-5 294 M
-( indicates the result of the requested operation. The value SSH_FX_OK) s
-5 283 M
-( indicates success, and all other values indicate failure.) s
-5 129 M
-(Ylonen & Lehtinen Expires April 1, 2002 [Page 20]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (20,21) 11
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 21 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH File Transfer Protocol October 2001) s
-5 690 M
-( Currently, the following values are defined \(other values may be) s
-5 679 M
-( defined by future versions of this protocol\):) s
-5 657 M
-( #define SSH_FX_OK 0) s
-5 646 M
-( #define SSH_FX_EOF 1) s
-5 635 M
-( #define SSH_FX_NO_SUCH_FILE 2) s
-5 624 M
-( #define SSH_FX_PERMISSION_DENIED 3) s
-5 613 M
-( #define SSH_FX_FAILURE 4) s
-5 602 M
-( #define SSH_FX_BAD_MESSAGE 5) s
-5 591 M
-( #define SSH_FX_NO_CONNECTION 6) s
-5 580 M
-( #define SSH_FX_CONNECTION_LOST 7) s
-5 569 M
-( #define SSH_FX_OP_UNSUPPORTED 8) s
-5 547 M
-( SSH_FX_OK) s
-5 536 M
-( Indicates successful completion of the operation.) s
-5 514 M
-( SSH_FX_EOF) s
-5 503 M
-( indicates end-of-file condition; for SSH_FX_READ it means that no) s
-5 492 M
-( more data is available in the file, and for SSH_FX_READDIR it) s
-5 481 M
-( indicates that no more files are contained in the directory.) s
-5 459 M
-( SSH_FX_NO_SUCH_FILE) s
-5 448 M
-( is returned when a reference is made to a file which should exist) s
-5 437 M
-( but doesn't.) s
-5 415 M
-( SSH_FX_PERMISSION_DENIED) s
-5 404 M
-( is returned when the authenticated user does not have sufficient) s
-5 393 M
-( permissions to perform the operation.) s
-5 371 M
-( SSH_FX_FAILURE) s
-5 360 M
-( is a generic catch-all error message; it should be returned if an) s
-5 349 M
-( error occurs for which there is no more specific error code) s
-5 338 M
-( defined.) s
-5 316 M
-( SSH_FX_BAD_MESSAGE) s
-5 305 M
-( may be returned if a badly formatted packet or protocol) s
-5 294 M
-( incompatibility is detected.) s
-5 272 M
-( SSH_FX_NO_CONNECTION) s
-5 261 M
-( is a pseudo-error which indicates that the client has no) s
-5 250 M
-( connection to the server \(it can only be generated locally by the) s
-5 239 M
-( client, and MUST NOT be returned by servers\).) s
-5 217 M
-( SSH_FX_CONNECTION_LOST) s
-5 206 M
-( is a pseudo-error which indicates that the connection to the) s
-5 195 M
-( server has been lost \(it can only be generated locally by the) s
-5 184 M
-( client, and MUST NOT be returned by servers\).) s
-5 129 M
-(Ylonen & Lehtinen Expires April 1, 2002 [Page 21]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 22 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH File Transfer Protocol October 2001) s
-5 690 M
-( SSH_FX_OP_UNSUPPORTED) s
-5 679 M
-( indicates that an attempt was made to perform an operation which) s
-5 668 M
-( is not supported for the server \(it may be generated locally by) s
-5 657 M
-( the client if e.g. the version number exchange indicates that a) s
-5 646 M
-( required feature is not supported by the server, or it may be) s
-5 635 M
-( returned by the server if the server does not implement an) s
-5 624 M
-( operation\).) s
-5 602 M
-( The SSH_FXP_HANDLE response has the following format:) s
-5 580 M
-( uint32 id) s
-5 569 M
-( string handle) s
-5 547 M
-( where `id' is the request identifier, and `handle' is an arbitrary) s
-5 536 M
-( string that identifies an open file or directory on the server. The) s
-5 525 M
-( handle is opaque to the client; the client MUST NOT attempt to) s
-5 514 M
-( interpret or modify it in any way. The length of the handle string) s
-5 503 M
-( MUST NOT exceed 256 data bytes.) s
-5 481 M
-( The SSH_FXP_DATA response has the following format:) s
-5 459 M
-( uint32 id) s
-5 448 M
-( string data) s
-5 426 M
-( where `id' is the request identifier, and `data' is an arbitrary byte) s
-5 415 M
-( string containing the requested data. The data string may be at most) s
-5 404 M
-( the number of bytes requested in a SSH_FXP_READ request, but may also) s
-5 393 M
-( be shorter if end of file is reached or if the read is from something) s
-5 382 M
-( other than a regular file.) s
-5 360 M
-( The SSH_FXP_NAME response has the following format:) s
-5 338 M
-( uint32 id) s
-5 327 M
-( uint32 count) s
-5 316 M
-( repeats count times:) s
-5 305 M
-( string filename) s
-5 294 M
-( string longname) s
-5 283 M
-( ATTRS attrs) s
-5 261 M
-( where `id' is the request identifier, `count' is the number of names) s
-5 250 M
-( returned in this response, and the remaining fields repeat `count') s
-5 239 M
-( times \(so that all three fields are first included for the first) s
-5 228 M
-( file, then for the second file, etc\). In the repeated part,) s
-5 217 M
-( `filename' is a file name being returned \(for SSH_FXP_READDIR, it) s
-5 206 M
-( will be a relative name within the directory, without any path) s
-5 195 M
-( components; for SSH_FXP_REALPATH it will be an absolute path name\),) s
-5 184 M
-( `longname' is an expanded format for the file name, similar to what) s
-5 173 M
-( is returned by "ls -l" on Unix systems, and `attrs' is the attributes) s
-5 129 M
-(Ylonen & Lehtinen Expires April 1, 2002 [Page 22]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (22,23) 12
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 23 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH File Transfer Protocol October 2001) s
-5 690 M
-( of the file as described in Section ``File Attributes''.) s
-5 668 M
-( The format of the `longname' field is unspecified by this protocol.) s
-5 657 M
-( It MUST be suitable for use in the output of a directory listing) s
-5 646 M
-( command \(in fact, the recommended operation for a directory listing) s
-5 635 M
-( command is to simply display this data\). However, clients SHOULD NOT) s
-5 624 M
-( attempt to parse the longname field for file attributes; they SHOULD) s
-5 613 M
-( use the attrs field instead.) s
-5 591 M
-( The recommended format for the longname field is as follows:) s
-5 569 M
-( -rwxr-xr-x 1 mjos staff 348911 Mar 25 14:29 t-filexfer) s
-5 558 M
-( 1234567890 123 12345678 12345678 12345678 123456789012) s
-5 536 M
-( Here, the first line is sample output, and the second field indicates) s
-5 525 M
-( widths of the various fields. Fields are separated by spaces. The) s
-5 514 M
-( first field lists file permissions for user, group, and others; the) s
-5 503 M
-( second field is link count; the third field is the name of the user) s
-5 492 M
-( who owns the file; the fourth field is the name of the group that) s
-5 481 M
-( owns the file; the fifth field is the size of the file in bytes; the) s
-5 470 M
-( sixth field \(which actually may contain spaces, but is fixed to 12) s
-5 459 M
-( characters\) is the file modification time, and the seventh field is) s
-5 448 M
-( the file name. Each field is specified to be a minimum of certain) s
-5 437 M
-( number of character positions \(indicated by the second line above\),) s
-5 426 M
-( but may also be longer if the data does not fit in the specified) s
-5 415 M
-( length.) s
-5 393 M
-( The SSH_FXP_ATTRS response has the following format:) s
-5 371 M
-( uint32 id) s
-5 360 M
-( ATTRS attrs) s
-5 338 M
-( where `id' is the request identifier, and `attrs' is the returned) s
-5 327 M
-( file attributes as described in Section ``File Attributes''.) s
-5 129 M
-(Ylonen & Lehtinen Expires April 1, 2002 [Page 23]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 24 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH File Transfer Protocol October 2001) s
-5 690 M
-(8. Vendor-Specific Extensions) s
-5 668 M
-( The SSH_FXP_EXTENDED request provides a generic extension mechanism) s
-5 657 M
-( for adding vendor-specific commands. The request has the following) s
-5 646 M
-( format:) s
-5 624 M
-( uint32 id) s
-5 613 M
-( string extended-request) s
-5 602 M
-( ... any request-specific data ...) s
-5 580 M
-( where `id' is the request identifier, and `extended-request' is a) s
-5 569 M
-( string of the format "name@domain", where domain is an internet) s
-5 558 M
-( domain name of the vendor defining the request. The rest of the) s
-5 547 M
-( request is completely vendor-specific, and servers should only) s
-5 536 M
-( attempt to interpret it if they recognize the `extended-request') s
-5 525 M
-( name.) s
-5 503 M
-( The server may respond to such requests using any of the response) s
-5 492 M
-( packets defined in Section ``Responses from the Server to the) s
-5 481 M
-( Client''. Additionally, the server may also respond with a) s
-5 470 M
-( SSH_FXP_EXTENDED_REPLY packet, as defined below. If the server does) s
-5 459 M
-( not recognize the `extended-request' name, then the server MUST) s
-5 448 M
-( respond with SSH_FXP_STATUS with error/status set to) s
-5 437 M
-( SSH_FX_OP_UNSUPPORTED.) s
-5 415 M
-( The SSH_FXP_EXTENDED_REPLY packet can be used to carry arbitrary) s
-5 404 M
-( extension-specific data from the server to the client. It is of the) s
-5 393 M
-( following format:) s
-5 371 M
-( uint32 id) s
-5 360 M
-( ... any request-specific data ...) s
-5 129 M
-(Ylonen & Lehtinen Expires April 1, 2002 [Page 24]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (24,25) 13
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 25 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH File Transfer Protocol October 2001) s
-5 690 M
-(9. Security Considerations) s
-5 668 M
-( This protocol assumes that it is run over a secure channel and that) s
-5 657 M
-( the endpoints of the channel have been authenticated. Thus, this) s
-5 646 M
-( protocol assumes that it is externally protected from network-level) s
-5 635 M
-( attacks.) s
-5 613 M
-( This protocol provides file system access to arbitrary files on the) s
-5 602 M
-( server \(only constrained by the server implementation\). It is the) s
-5 591 M
-( responsibility of the server implementation to enforce any access) s
-5 580 M
-( controls that may be required to limit the access allowed for any) s
-5 569 M
-( particular user \(the user being authenticated externally to this) s
-5 558 M
-( protocol, typically using the SSH User Authentication Protocol [6].) s
-5 536 M
-( Care must be taken in the server implementation to check the validity) s
-5 525 M
-( of received file handle strings. The server should not rely on them) s
-5 514 M
-( directly; it MUST check the validity of each handle before relying on) s
-5 503 M
-( it.) s
-5 129 M
-(Ylonen & Lehtinen Expires April 1, 2002 [Page 25]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 26 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH File Transfer Protocol October 2001) s
-5 690 M
-(10. Changes from previous protocol versions) s
-5 668 M
-( The SSH File Transfer Protocol has changed over time, before it's) s
-5 657 M
-( standardization. The following is a description of the incompatible) s
-5 646 M
-( changes between different versions.) s
-5 624 M
-(10.1 Changes between versions 3 and 2) s
-5 602 M
-( o The SSH_FXP_READLINK and SSH_FXP_SYMLINK messages were added.) s
-5 580 M
-( o The SSH_FXP_EXTENDED and SSH_FXP_EXTENDED_REPLY messages were) s
-5 569 M
-( added.) s
-5 547 M
-( o The SSH_FXP_STATUS message was changed to include fields `error) s
-5 536 M
-( message' and `language tag'.) s
-5 503 M
-(10.2 Changes between versions 2 and 1) s
-5 481 M
-( o The SSH_FXP_RENAME message was added.) s
-5 448 M
-(10.3 Changes between versions 1 and 0) s
-5 426 M
-( o Implementation changes, no actual protocol changes.) s
-5 129 M
-(Ylonen & Lehtinen Expires April 1, 2002 [Page 26]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (26,27) 14
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 27 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH File Transfer Protocol October 2001) s
-5 690 M
-(11. Trademark Issues) s
-5 668 M
-( "ssh" is a registered trademark of SSH Communications Security Corp) s
-5 657 M
-( in the United States and/or other countries.) s
-5 129 M
-(Ylonen & Lehtinen Expires April 1, 2002 [Page 27]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 28 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH File Transfer Protocol October 2001) s
-5 690 M
-(References) s
-5 668 M
-( [1] Dierks, T., Allen, C., Treese, W., Karlton, P., Freier, A. and) s
-5 657 M
-( P. Kocher, "The TLS Protocol Version 1.0", RFC 2246, January) s
-5 646 M
-( 1999.) s
-5 624 M
-( [2] Institute of Electrical and Electronics Engineers, "Information) s
-5 613 M
-( Technology - Portable Operating System Interface \(POSIX\) - Part) s
-5 602 M
-( 1: System Application Program Interface \(API\) [C Language]",) s
-5 591 M
-( IEEE Standard 1003.2, 1996.) s
-5 569 M
-( [3] Rinne, T., Ylonen, T., Kivinen, T., Saarinen, M. and S.) s
-5 558 M
-( Lehtinen, "SSH Protocol Architecture", draft-ietf-secsh-) s
-5 547 M
-( architecture-09 \(work in progress\), July 2001.) s
-5 525 M
-( [4] Rinne, T., Ylonen, T., Kivinen, T., Saarinen, M. and S.) s
-5 514 M
-( Lehtinen, "SSH Protocol Transport Protocol", draft-ietf-secsh-) s
-5 503 M
-( architecture-09 \(work in progress\), July 2001.) s
-5 481 M
-( [5] Rinne, T., Ylonen, T., Kivinen, T., Saarinen, M. and S.) s
-5 470 M
-( Lehtinen, "SSH Connection Protocol", draft-ietf-secsh-connect-11) s
-5 459 M
-( \(work in progress\), July 2001.) s
-5 437 M
-( [6] Rinne, T., Ylonen, T., Kivinen, T., Saarinen, M. and S.) s
-5 426 M
-( Lehtinen, "SSH Authentication Protocol", draft-ietf-secsh-) s
-5 415 M
-( userauth-11 \(work in progress\), July 2001.) s
-5 382 M
-(Authors' Addresses) s
-5 360 M
-( Tatu Ylonen) s
-5 349 M
-( SSH Communications Security Corp) s
-5 338 M
-( Fredrikinkatu 42) s
-5 327 M
-( HELSINKI FIN-00100) s
-5 316 M
-( Finland) s
-5 294 M
-( EMail: [email protected]) s
-5 261 M
-( Sami Lehtinen) s
-5 250 M
-( SSH Communications Security Corp) s
-5 239 M
-( Fredrikinkatu 42) s
-5 228 M
-( HELSINKI FIN-00100) s
-5 217 M
-( Finland) s
-5 195 M
-( EMail: [email protected]) s
-5 129 M
-(Ylonen & Lehtinen Expires April 1, 2002 [Page 28]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (28,29) 15
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 29 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH File Transfer Protocol October 2001) s
-5 690 M
-(Full Copyright Statement) s
-5 668 M
-( Copyright \(C\) The Internet Society \(2001\). All Rights Reserved.) s
-5 646 M
-( This document and translations of it may be copied and furnished to) s
-5 635 M
-( others, and derivative works that comment on or otherwise explain it) s
-5 624 M
-( or assist in its implementation may be prepared, copied, published) s
-5 613 M
-( and distributed, in whole or in part, without restriction of any) s
-5 602 M
-( kind, provided that the above copyright notice and this paragraph are) s
-5 591 M
-( included on all such copies and derivative works. However, this) s
-5 580 M
-( document itself may not be modified in any way, such as by removing) s
-5 569 M
-( the copyright notice or references to the Internet Society or other) s
-5 558 M
-( Internet organizations, except as needed for the purpose of) s
-5 547 M
-( developing Internet standards in which case the procedures for) s
-5 536 M
-( copyrights defined in the Internet Standards process must be) s
-5 525 M
-( followed, or as required to translate it into languages other than) s
-5 514 M
-( English.) s
-5 492 M
-( The limited permissions granted above are perpetual and will not be) s
-5 481 M
-( revoked by the Internet Society or its successors or assigns.) s
-5 459 M
-( This document and the information contained herein is provided on an) s
-5 448 M
-( "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING) s
-5 437 M
-( TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING) s
-5 426 M
-( BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION) s
-5 415 M
-( HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF) s
-5 404 M
-( MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.) s
-5 382 M
-(Acknowledgement) s
-5 360 M
-( Funding for the RFC Editor function is currently provided by the) s
-5 349 M
-( Internet Society.) s
-5 129 M
-(Ylonen & Lehtinen Expires April 1, 2002 [Page 29]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 30 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-_R
-S
-PStoPSsaved restore
-%%Trailer
-%%Pages: 30
-%%DocumentNeededResources: font Courier-Bold Courier
-%%EOF
diff --git a/lib/ssh/doc/standard/draft-ietf-secsh-filexfer-02.txt b/lib/ssh/doc/standard/draft-ietf-secsh-filexfer-02.txt
deleted file mode 100644
index c4ec8c1125..0000000000
--- a/lib/ssh/doc/standard/draft-ietf-secsh-filexfer-02.txt
+++ /dev/null
@@ -1,1627 +0,0 @@
-
-
-
-Network Working Group T. Ylonen
-Internet-Draft S. Lehtinen
-Expires: April 1, 2002 SSH Communications Security Corp
- October 2001
-
-
- SSH File Transfer Protocol
- draft-ietf-secsh-filexfer-02.txt
-
-Status of this Memo
-
- This document is an Internet-Draft and is in full conformance with
- all provisions of Section 10 of RFC2026.
-
- Internet-Drafts are working documents of the Internet Engineering
- Task Force (IETF), its areas, and its working groups. Note that
- other groups may also distribute working documents as Internet-
- Drafts.
-
- Internet-Drafts are draft documents valid for a maximum of six months
- and may be updated, replaced, or obsoleted by other documents at any
- time. It is inappropriate to use Internet-Drafts as reference
- material or to cite them other than as "work in progress."
-
- The list of current Internet-Drafts can be accessed at http://
- www.ietf.org/ietf/1id-abstracts.txt.
-
- The list of Internet-Draft Shadow Directories can be accessed at
- http://www.ietf.org/shadow.html.
-
- This Internet-Draft will expire on April 1, 2002.
-
-Copyright Notice
-
- Copyright (C) The Internet Society (2001). All Rights Reserved.
-
-Abstract
-
- The SSH File Transfer Protocol provides secure file transfer
- functionality over any reliable data stream. It is the standard file
- transfer protocol for use with the SSH2 protocol. This document
- describes the file transfer protocol and its interface to the SSH2
- protocol suite.
-
-
-
-
-
-
-
-
-
-Ylonen & Lehtinen Expires April 1, 2002 [Page 1]
-
-Internet-Draft SSH File Transfer Protocol October 2001
-
-
-Table of Contents
-
- 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3
- 2. Use with the SSH Connection Protocol . . . . . . . . . . . . 4
- 3. General Packet Format . . . . . . . . . . . . . . . . . . . 5
- 4. Protocol Initialization . . . . . . . . . . . . . . . . . . 7
- 5. File Attributes . . . . . . . . . . . . . . . . . . . . . . 8
- 6. Requests From the Client to the Server . . . . . . . . . . . 10
- 6.1 Request Synchronization and Reordering . . . . . . . . . . . 10
- 6.2 File Names . . . . . . . . . . . . . . . . . . . . . . . . . 11
- 6.3 Opening, Creating, and Closing Files . . . . . . . . . . . . 11
- 6.4 Reading and Writing . . . . . . . . . . . . . . . . . . . . 13
- 6.5 Removing and Renaming Files . . . . . . . . . . . . . . . . 14
- 6.6 Creating and Deleting Directories . . . . . . . . . . . . . 15
- 6.7 Scanning Directories . . . . . . . . . . . . . . . . . . . . 15
- 6.8 Retrieving File Attributes . . . . . . . . . . . . . . . . . 16
- 6.9 Setting File Attributes . . . . . . . . . . . . . . . . . . 17
- 6.10 Dealing with Symbolic links . . . . . . . . . . . . . . . . 18
- 6.11 Canonicalizing the Server-Side Path Name . . . . . . . . . . 18
- 7. Responses from the Server to the Client . . . . . . . . . . 20
- 8. Vendor-Specific Extensions . . . . . . . . . . . . . . . . . 24
- 9. Security Considerations . . . . . . . . . . . . . . . . . . 25
- 10. Changes from previous protocol versions . . . . . . . . . . 26
- 10.1 Changes between versions 3 and 2 . . . . . . . . . . . . . . 26
- 10.2 Changes between versions 2 and 1 . . . . . . . . . . . . . . 26
- 10.3 Changes between versions 1 and 0 . . . . . . . . . . . . . . 26
- 11. Trademark Issues . . . . . . . . . . . . . . . . . . . . . . 27
- References . . . . . . . . . . . . . . . . . . . . . . . . . 28
- Authors' Addresses . . . . . . . . . . . . . . . . . . . . . 28
- Full Copyright Statement . . . . . . . . . . . . . . . . . . 29
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Ylonen & Lehtinen Expires April 1, 2002 [Page 2]
-
-Internet-Draft SSH File Transfer Protocol October 2001
-
-
-1. Introduction
-
- This protocol provides secure file transfer (and more generally file
- system access) functionality over a reliable data stream, such as a
- channel in the SSH2 protocol [3].
-
- This protocol is designed so that it could be used to implement a
- secure remote file system service, as well as a secure file transfer
- service.
-
- This protocol assumes that it runs over a secure channel, and that
- the server has already authenticated the user at the client end, and
- that the identity of the client user is externally available to the
- server implementation.
-
- In general, this protocol follows a simple request-response model.
- Each request and response contains a sequence number and multiple
- requests may be pending simultaneously. There are a relatively large
- number of different request messages, but a small number of possible
- response messages. Each request has one or more response messages
- that may be returned in result (e.g., a read either returns data or
- reports error status).
-
- The packet format descriptions in this specification follow the
- notation presented in the secsh architecture draft.[3].
-
- Even though this protocol is described in the context of the SSH2
- protocol, this protocol is general and independent of the rest of the
- SSH2 protocol suite. It could be used in a number of different
- applications, such as secure file transfer over TLS RFC 2246 [1] and
- transfer of management information in VPN applications.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Ylonen & Lehtinen Expires April 1, 2002 [Page 3]
-
-Internet-Draft SSH File Transfer Protocol October 2001
-
-
-2. Use with the SSH Connection Protocol
-
- When used with the SSH2 Protocol suite, this protocol is intended to
- be used from the SSH Connection Protocol [5] as a subsystem, as
- described in section ``Starting a Shell or a Command''. The
- subsystem name used with this protocol is "sftp".
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Ylonen & Lehtinen Expires April 1, 2002 [Page 4]
-
-Internet-Draft SSH File Transfer Protocol October 2001
-
-
-3. General Packet Format
-
- All packets transmitted over the secure connection are of the
- following format:
-
- uint32 length
- byte type
- byte[length - 1] data payload
-
- That is, they are just data preceded by 32-bit length and 8-bit type
- fields. The `length' is the length of the data area, and does not
- include the `length' field itself. The format and interpretation of
- the data area depends on the packet type.
-
- All packet descriptions below only specify the packet type and the
- data that goes into the data field. Thus, they should be prefixed by
- the `length' and `type' fields.
-
- The maximum size of a packet is in practice determined by the client
- (the maximum size of read or write requests that it sends, plus a few
- bytes of packet overhead). All servers SHOULD support packets of at
- least 34000 bytes (where the packet size refers to the full length,
- including the header above). This should allow for reads and writes
- of at most 32768 bytes.
-
- There is no limit on the number of outstanding (non-acknowledged)
- requests that the client may send to the server. In practice this is
- limited by the buffering available on the data stream and the queuing
- performed by the server. If the server's queues are full, it should
- not read any more data from the stream, and flow control will prevent
- the client from sending more requests. Note, however, that while
- there is no restriction on the protocol level, the client's API may
- provide a limit in order to prevent infinite queuing of outgoing
- requests at the client.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Ylonen & Lehtinen Expires April 1, 2002 [Page 5]
-
-Internet-Draft SSH File Transfer Protocol October 2001
-
-
- The following values are defined for packet types.
-
- #define SSH_FXP_INIT 1
- #define SSH_FXP_VERSION 2
- #define SSH_FXP_OPEN 3
- #define SSH_FXP_CLOSE 4
- #define SSH_FXP_READ 5
- #define SSH_FXP_WRITE 6
- #define SSH_FXP_LSTAT 7
- #define SSH_FXP_FSTAT 8
- #define SSH_FXP_SETSTAT 9
- #define SSH_FXP_FSETSTAT 10
- #define SSH_FXP_OPENDIR 11
- #define SSH_FXP_READDIR 12
- #define SSH_FXP_REMOVE 13
- #define SSH_FXP_MKDIR 14
- #define SSH_FXP_RMDIR 15
- #define SSH_FXP_REALPATH 16
- #define SSH_FXP_STAT 17
- #define SSH_FXP_RENAME 18
- #define SSH_FXP_READLINK 19
- #define SSH_FXP_SYMLINK 20
- #define SSH_FXP_STATUS 101
- #define SSH_FXP_HANDLE 102
- #define SSH_FXP_DATA 103
- #define SSH_FXP_NAME 104
- #define SSH_FXP_ATTRS 105
- #define SSH_FXP_EXTENDED 200
- #define SSH_FXP_EXTENDED_REPLY 201
-
- Additional packet types should only be defined if the protocol
- version number (see Section ``Protocol Initialization'') is
- incremented, and their use MUST be negotiated using the version
- number. However, the SSH_FXP_EXTENDED and SSH_FXP_EXTENDED_REPLY
- packets can be used to implement vendor-specific extensions. See
- Section ``Vendor-Specific-Extensions'' for more details.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Ylonen & Lehtinen Expires April 1, 2002 [Page 6]
-
-Internet-Draft SSH File Transfer Protocol October 2001
-
-
-4. Protocol Initialization
-
- When the file transfer protocol starts, it first sends a SSH_FXP_INIT
- (including its version number) packet to the server. The server
- responds with a SSH_FXP_VERSION packet, supplying the lowest of its
- own and the client's version number. Both parties should from then
- on adhere to particular version of the protocol.
-
- The SSH_FXP_INIT packet (from client to server) has the following
- data:
-
- uint32 version
- <extension data>
-
- The SSH_FXP_VERSION packet (from server to client) has the following
- data:
-
- uint32 version
- <extension data>
-
- The version number of the protocol specified in this document is 3.
- The version number should be incremented for each incompatible
- revision of this protocol.
-
- The extension data in the above packets may be empty, or may be a
- sequence of
-
- string extension_name
- string extension_data
-
- pairs (both strings MUST always be present if one is, but the
- `extension_data' string may be of zero length). If present, these
- strings indicate extensions to the baseline protocol. The
- `extension_name' field(s) identify the name of the extension. The
- name should be of the form "name@domain", where the domain is the DNS
- domain name of the organization defining the extension. Additional
- names that are not of this format may be defined later by the IETF.
- Implementations MUST silently ignore any extensions whose name they
- do not recognize.
-
-
-
-
-
-
-
-
-
-
-
-
-Ylonen & Lehtinen Expires April 1, 2002 [Page 7]
-
-Internet-Draft SSH File Transfer Protocol October 2001
-
-
-5. File Attributes
-
- A new compound data type is defined for encoding file attributes. It
- is basically just a combination of elementary types, but is defined
- once because of the non-trivial description of the fields and to
- ensure maintainability.
-
- The same encoding is used both when returning file attributes from
- the server and when sending file attributes to the server. When
- sending it to the server, the flags field specifies which attributes
- are included, and the server will use default values for the
- remaining attributes (or will not modify the values of remaining
- attributes). When receiving attributes from the server, the flags
- specify which attributes are included in the returned data. The
- server normally returns all attributes it knows about.
-
- uint32 flags
- uint64 size present only if flag SSH_FILEXFER_ATTR_SIZE
- uint32 uid present only if flag SSH_FILEXFER_ATTR_UIDGID
- uint32 gid present only if flag SSH_FILEXFER_ATTR_UIDGID
- uint32 permissions present only if flag SSH_FILEXFER_ATTR_PERMISSIONS
- uint32 atime present only if flag SSH_FILEXFER_ACMODTIME
- uint32 mtime present only if flag SSH_FILEXFER_ACMODTIME
- uint32 extended_count present only if flag SSH_FILEXFER_ATTR_EXTENDED
- string extended_type
- string extended_data
- ... more extended data (extended_type - extended_data pairs),
- so that number of pairs equals extended_count
-
- The `flags' specify which of the fields are present. Those fields
- for which the corresponding flag is not set are not present (not
- included in the packet). New flags can only be added by incrementing
- the protocol version number (or by using the extension mechanism
- described below).
-
- The `size' field specifies the size of the file in bytes.
-
- The `uid' and `gid' fields contain numeric Unix-like user and group
- identifiers, respectively.
-
- The `permissions' field contains a bit mask of file permissions as
- defined by posix [1].
-
- The `atime' and `mtime' contain the access and modification times of
- the files, respectively. They are represented as seconds from Jan 1,
- 1970 in UTC.
-
- The SSH_FILEXFER_ATTR_EXTENDED flag provides a general extension
-
-
-
-Ylonen & Lehtinen Expires April 1, 2002 [Page 8]
-
-Internet-Draft SSH File Transfer Protocol October 2001
-
-
- mechanism for vendor-specific extensions. If the flag is specified,
- then the `extended_count' field is present. It specifies the number
- of extended_type-extended_data pairs that follow. Each of these
- pairs specifies an extended attribute. For each of the attributes,
- the extended_type field should be a string of the format
- "name@domain", where "domain" is a valid, registered domain name and
- "name" identifies the method. The IETF may later standardize certain
- names that deviate from this format (e.g., that do not contain the
- "@" sign). The interpretation of `extended_data' depends on the
- type. Implementations SHOULD ignore extended data fields that they
- do not understand.
-
- Additional fields can be added to the attributes by either defining
- additional bits to the flags field to indicate their presence, or by
- defining extended attributes for them. The extended attributes
- mechanism is recommended for most purposes; additional flags bits
- should only be defined by an IETF standards action that also
- increments the protocol version number. The use of such new fields
- MUST be negotiated by the version number in the protocol exchange.
- It is a protocol error if a packet with unsupported protocol bits is
- received.
-
- The flags bits are defined to have the following values:
-
- #define SSH_FILEXFER_ATTR_SIZE 0x00000001
- #define SSH_FILEXFER_ATTR_UIDGID 0x00000002
- #define SSH_FILEXFER_ATTR_PERMISSIONS 0x00000004
- #define SSH_FILEXFER_ATTR_ACMODTIME 0x00000008
- #define SSH_FILEXFER_ATTR_EXTENDED 0x80000000
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Ylonen & Lehtinen Expires April 1, 2002 [Page 9]
-
-Internet-Draft SSH File Transfer Protocol October 2001
-
-
-6. Requests From the Client to the Server
-
- Requests from the client to the server represent the various file
- system operations. Each request begins with an `id' field, which is
- a 32-bit identifier identifying the request (selected by the client).
- The same identifier will be returned in the response to the request.
- One possible implementation of it is a monotonically increasing
- request sequence number (modulo 2^32).
-
- Many operations in the protocol operate on open files. The
- SSH_FXP_OPEN request can return a file handle (which is an opaque
- variable-length string) which may be used to access the file later
- (e.g. in a read operation). The client MUST NOT send requests the
- server with bogus or closed handles. However, the server MUST
- perform adequate checks on the handle in order to avoid security
- risks due to fabricated handles.
-
- This design allows either stateful and stateless server
- implementation, as well as an implementation which caches state
- between requests but may also flush it. The contents of the file
- handle string are entirely up to the server and its design. The
- client should not modify or attempt to interpret the file handle
- strings.
-
- The file handle strings MUST NOT be longer than 256 bytes.
-
-6.1 Request Synchronization and Reordering
-
- The protocol and implementations MUST process requests relating to
- the same file in the order in which they are received. In other
- words, if an application submits multiple requests to the server, the
- results in the responses will be the same as if it had sent the
- requests one at a time and waited for the response in each case. For
- example, the server may process non-overlapping read/write requests
- to the same file in parallel, but overlapping reads and writes cannot
- be reordered or parallelized. However, there are no ordering
- restrictions on the server for processing requests from two different
- file transfer connections. The server may interleave and parallelize
- them at will.
-
- There are no restrictions on the order in which responses to
- outstanding requests are delivered to the client, except that the
- server must ensure fairness in the sense that processing of no
- request will be indefinitely delayed even if the client is sending
- other requests so that there are multiple outstanding requests all
- the time.
-
-
-
-
-
-Ylonen & Lehtinen Expires April 1, 2002 [Page 10]
-
-Internet-Draft SSH File Transfer Protocol October 2001
-
-
-6.2 File Names
-
- This protocol represents file names as strings. File names are
- assumed to use the slash ('/') character as a directory separator.
-
- File names starting with a slash are "absolute", and are relative to
- the root of the file system. Names starting with any other character
- are relative to the user's default directory (home directory). Note
- that identifying the user is assumed to take place outside of this
- protocol.
-
- Servers SHOULD interpret a path name component ".." as referring to
- the parent directory, and "." as referring to the current directory.
- If the server implementation limits access to certain parts of the
- file system, it must be extra careful in parsing file names when
- enforcing such restrictions. There have been numerous reported
- security bugs where a ".." in a path name has allowed access outside
- the intended area.
-
- An empty path name is valid, and it refers to the user's default
- directory (usually the user's home directory).
-
- Otherwise, no syntax is defined for file names by this specification.
- Clients should not make any other assumptions; however, they can
- splice path name components returned by SSH_FXP_READDIR together
- using a slash ('/') as the separator, and that will work as expected.
-
- It is understood that the lack of well-defined semantics for file
- names may cause interoperability problems between clients and servers
- using radically different operating systems. However, this approach
- is known to work acceptably with most systems, and alternative
- approaches that e.g. treat file names as sequences of structured
- components are quite complicated.
-
-6.3 Opening, Creating, and Closing Files
-
- Files are opened and created using the SSH_FXP_OPEN message, whose
- data part is as follows:
-
- uint32 id
- string filename
- uint32 pflags
- ATTRS attrs
-
- The `id' field is the request identifier as for all requests.
-
- The `filename' field specifies the file name. See Section ``File
- Names'' for more information.
-
-
-
-Ylonen & Lehtinen Expires April 1, 2002 [Page 11]
-
-Internet-Draft SSH File Transfer Protocol October 2001
-
-
- The `pflags' field is a bitmask. The following bits have been
- defined.
-
- #define SSH_FXF_READ 0x00000001
- #define SSH_FXF_WRITE 0x00000002
- #define SSH_FXF_APPEND 0x00000004
- #define SSH_FXF_CREAT 0x00000008
- #define SSH_FXF_TRUNC 0x00000010
- #define SSH_FXF_EXCL 0x00000020
-
- These have the following meanings:
-
- SSH_FXF_READ
- Open the file for reading.
-
- SSH_FXF_WRITE
- Open the file for writing. If both this and SSH_FXF_READ are
- specified, the file is opened for both reading and writing.
-
- SSH_FXF_APPEND
- Force all writes to append data at the end of the file.
-
- SSH_FXF_CREAT
- If this flag is specified, then a new file will be created if one
- does not already exist (if O_TRUNC is specified, the new file will
- be truncated to zero length if it previously exists).
-
- SSH_FXF_TRUNC
- Forces an existing file with the same name to be truncated to zero
- length when creating a file by specifying SSH_FXF_CREAT.
- SSH_FXF_CREAT MUST also be specified if this flag is used.
-
- SSH_FXF_EXCL
- Causes the request to fail if the named file already exists.
- SSH_FXF_CREAT MUST also be specified if this flag is used.
-
- The `attrs' field specifies the initial attributes for the file.
- Default values will be used for those attributes that are not
- specified. See Section ``File Attributes'' for more information.
-
- Regardless the server operating system, the file will always be
- opened in "binary" mode (i.e., no translations between different
- character sets and newline encodings).
-
- The response to this message will be either SSH_FXP_HANDLE (if the
- operation is successful) or SSH_FXP_STATUS (if the operation fails).
-
-
-
-
-
-Ylonen & Lehtinen Expires April 1, 2002 [Page 12]
-
-Internet-Draft SSH File Transfer Protocol October 2001
-
-
- A file is closed by using the SSH_FXP_CLOSE request. Its data field
- has the following format:
-
- uint32 id
- string handle
-
- where `id' is the request identifier, and `handle' is a handle
- previously returned in the response to SSH_FXP_OPEN or
- SSH_FXP_OPENDIR. The handle becomes invalid immediately after this
- request has been sent.
-
- The response to this request will be a SSH_FXP_STATUS message. One
- should note that on some server platforms even a close can fail.
- This can happen e.g. if the server operating system caches writes,
- and an error occurs while flushing cached writes during the close.
-
-6.4 Reading and Writing
-
- Once a file has been opened, it can be read using the SSH_FXP_READ
- message, which has the following format:
-
- uint32 id
- string handle
- uint64 offset
- uint32 len
-
- where `id' is the request identifier, `handle' is an open file handle
- returned by SSH_FXP_OPEN, `offset' is the offset (in bytes) relative
- to the beginning of the file from where to start reading, and `len'
- is the maximum number of bytes to read.
-
- In response to this request, the server will read as many bytes as it
- can from the file (up to `len'), and return them in a SSH_FXP_DATA
- message. If an error occurs or EOF is encountered before reading any
- data, the server will respond with SSH_FXP_STATUS. For normal disk
- files, it is guaranteed that this will read the specified number of
- bytes, or up to end of file. For e.g. device files this may return
- fewer bytes than requested.
-
- Writing to a file is achieved using the SSH_FXP_WRITE message, which
- has the following format:
-
- uint32 id
- string handle
- uint64 offset
- string data
-
- where `id' is a request identifier, `handle' is a file handle
-
-
-
-Ylonen & Lehtinen Expires April 1, 2002 [Page 13]
-
-Internet-Draft SSH File Transfer Protocol October 2001
-
-
- returned by SSH_FXP_OPEN, `offset' is the offset (in bytes) from the
- beginning of the file where to start writing, and `data' is the data
- to be written.
-
- The write will extend the file if writing beyond the end of the file.
- It is legal to write way beyond the end of the file; the semantics
- are to write zeroes from the end of the file to the specified offset
- and then the data. On most operating systems, such writes do not
- allocate disk space but instead leave "holes" in the file.
-
- The server responds to a write request with a SSH_FXP_STATUS message.
-
-6.5 Removing and Renaming Files
-
- Files can be removed using the SSH_FXP_REMOVE message. It has the
- following format:
-
- uint32 id
- string filename
-
- where `id' is the request identifier and `filename' is the name of
- the file to be removed. See Section ``File Names'' for more
- information. This request cannot be used to remove directories.
-
- The server will respond to this request with a SSH_FXP_STATUS
- message.
-
- Files (and directories) can be renamed using the SSH_FXP_RENAME
- message. Its data is as follows:
-
- uint32 id
- string oldpath
- string newpath
-
- where `id' is the request identifier, `oldpath' is the name of an
- existing file or directory, and `newpath' is the new name for the
- file or directory. It is an error if there already exists a file
- with the name specified by newpath. The server may also fail rename
- requests in other situations, for example if `oldpath' and `newpath'
- point to different file systems on the server.
-
- The server will respond to this request with a SSH_FXP_STATUS
- message.
-
-
-
-
-
-
-
-
-Ylonen & Lehtinen Expires April 1, 2002 [Page 14]
-
-Internet-Draft SSH File Transfer Protocol October 2001
-
-
-6.6 Creating and Deleting Directories
-
- New directories can be created using the SSH_FXP_MKDIR request. It
- has the following format:
-
- uint32 id
- string path
- ATTRS attrs
-
- where `id' is the request identifier, `path' and `attrs' specifies
- the modifications to be made to its attributes. See Section ``File
- Names'' for more information on file names. Attributes are discussed
- in more detail in Section ``File Attributes''. specifies the
- directory to be created. An error will be returned if a file or
- directory with the specified path already exists. The server will
- respond to this request with a SSH_FXP_STATUS message.
-
- Directories can be removed using the SSH_FXP_RMDIR request, which
- has the following format:
-
- uint32 id
- string path
-
- where `id' is the request identifier, and `path' specifies the
- directory to be removed. See Section ``File Names'' for more
- information on file names. An error will be returned if no directory
- with the specified path exists, or if the specified directory is not
- empty, or if the path specified a file system object other than a
- directory. The server responds to this request with a SSH_FXP_STATUS
- message.
-
-6.7 Scanning Directories
-
- The files in a directory can be listed using the SSH_FXP_OPENDIR and
- SSH_FXP_READDIR requests. Each SSH_FXP_READDIR request returns one
- or more file names with full file attributes for each file. The
- client should call SSH_FXP_READDIR repeatedly until it has found the
- file it is looking for or until the server responds with a
- SSH_FXP_STATUS message indicating an error (normally SSH_FX_EOF if
- there are no more files in the directory). The client should then
- close the handle using the SSH_FXP_CLOSE request.
-
-
-
-
-
-
-
-
-
-
-Ylonen & Lehtinen Expires April 1, 2002 [Page 15]
-
-Internet-Draft SSH File Transfer Protocol October 2001
-
-
- The SSH_FXP_OPENDIR opens a directory for reading. It has the
- following format:
-
- uint32 id
- string path
-
- where `id' is the request identifier and `path' is the path name of
- the directory to be listed (without any trailing slash). See Section
- ``File Names'' for more information on file names. This will return
- an error if the path does not specify a directory or if the directory
- is not readable. The server will respond to this request with either
- a SSH_FXP_HANDLE or a SSH_FXP_STATUS message.
-
- Once the directory has been successfully opened, files (and
- directories) contained in it can be listed using SSH_FXP_READDIR
- requests. These are of the format
-
- uint32 id
- string handle
-
- where `id' is the request identifier, and `handle' is a handle
- returned by SSH_FXP_OPENDIR. (It is a protocol error to attempt to
- use an ordinary file handle returned by SSH_FXP_OPEN.)
-
- The server responds to this request with either a SSH_FXP_NAME or a
- SSH_FXP_STATUS message. One or more names may be returned at a time.
- Full status information is returned for each name in order to speed
- up typical directory listings.
-
- When the client no longer wishes to read more names from the
- directory, it SHOULD call SSH_FXP_CLOSE for the handle. The handle
- should be closed regardless of whether an error has occurred or not.
-
-6.8 Retrieving File Attributes
-
- Very often, file attributes are automatically returned by
- SSH_FXP_READDIR. However, sometimes there is need to specifically
- retrieve the attributes for a named file. This can be done using the
- SSH_FXP_STAT, SSH_FXP_LSTAT and SSH_FXP_FSTAT requests.
-
- SSH_FXP_STAT and SSH_FXP_LSTAT only differ in that SSH_FXP_STAT
- follows symbolic links on the server, whereas SSH_FXP_LSTAT does not
- follow symbolic links. Both have the same format:
-
- uint32 id
- string path
-
- where `id' is the request identifier, and `path' specifies the file
-
-
-
-Ylonen & Lehtinen Expires April 1, 2002 [Page 16]
-
-Internet-Draft SSH File Transfer Protocol October 2001
-
-
- system object for which status is to be returned. The server
- responds to this request with either SSH_FXP_ATTRS or SSH_FXP_STATUS.
-
- SSH_FXP_FSTAT differs from the others in that it returns status
- information for an open file (identified by the file handle). Its
- format is as follows:
-
- uint32 id
- string handle
-
- where `id' is the request identifier and `handle' is a file handle
- returned by SSH_FXP_OPEN. The server responds to this request with
- SSH_FXP_ATTRS or SSH_FXP_STATUS.
-
-6.9 Setting File Attributes
-
- File attributes may be modified using the SSH_FXP_SETSTAT and
- SSH_FXP_FSETSTAT requests. These requests are used for operations
- such as changing the ownership, permissions or access times, as well
- as for truncating a file.
-
- The SSH_FXP_SETSTAT request is of the following format:
-
- uint32 id
- string path
- ATTRS attrs
-
- where `id' is the request identifier, `path' specifies the file
- system object (e.g. file or directory) whose attributes are to be
- modified, and `attrs' specifies the modifications to be made to its
- attributes. Attributes are discussed in more detail in Section
- ``File Attributes''.
-
- An error will be returned if the specified file system object does
- not exist or the user does not have sufficient rights to modify the
- specified attributes. The server responds to this request with a
- SSH_FXP_STATUS message.
-
- The SSH_FXP_FSETSTAT request modifies the attributes of a file which
- is already open. It has the following format:
-
- uint32 id
- string handle
- ATTRS attrs
-
- where `id' is the request identifier, `handle' (MUST be returned by
- SSH_FXP_OPEN) identifies the file whose attributes are to be
- modified, and `attrs' specifies the modifications to be made to its
-
-
-
-Ylonen & Lehtinen Expires April 1, 2002 [Page 17]
-
-Internet-Draft SSH File Transfer Protocol October 2001
-
-
- attributes. Attributes are discussed in more detail in Section
- ``File Attributes''. The server will respond to this request with
- SSH_FXP_STATUS.
-
-6.10 Dealing with Symbolic links
-
- The SSH_FXP_READLINK request may be used to read the target of a
- symbolic link. It would have a data part as follows:
-
- uint32 id
- string path
-
- where `id' is the request identifier and `path' specifies the path
- name of the symlink to be read.
-
- The server will respond with a SSH_FXP_NAME packet containing only
- one name and a dummy attributes value. The name in the returned
- packet contains the target of the link. If an error occurs, the
- server may respond with SSH_FXP_STATUS.
-
- The SSH_FXP_SYMLINK request will create a symbolic link on the
- server. It is of the following format
-
- uint32 id
- string linkpath
- string targetpath
-
- where `id' is the request identifier, `linkpath' specifies the path
- name of the symlink to be created and `targetpath' specifies the
- target of the symlink. The server shall respond with a
- SSH_FXP_STATUS indicating either success (SSH_FX_OK) or an error
- condition.
-
-6.11 Canonicalizing the Server-Side Path Name
-
- The SSH_FXP_REALPATH request can be used to have the server
- canonicalize any given path name to an absolute path. This is useful
- for converting path names containing ".." components or relative
- pathnames without a leading slash into absolute paths. The format of
- the request is as follows:
-
- uint32 id
- string path
-
- where `id' is the request identifier and `path' specifies the path
- name to be canonicalized. The server will respond with a
- SSH_FXP_NAME packet containing only one name and a dummy attributes
- value. The name is the returned packet will be in canonical form.
-
-
-
-Ylonen & Lehtinen Expires April 1, 2002 [Page 18]
-
-Internet-Draft SSH File Transfer Protocol October 2001
-
-
- If an error occurs, the server may also respond with SSH_FXP_STATUS.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Ylonen & Lehtinen Expires April 1, 2002 [Page 19]
-
-Internet-Draft SSH File Transfer Protocol October 2001
-
-
-7. Responses from the Server to the Client
-
- The server responds to the client using one of a few response
- packets. All requests can return a SSH_FXP_STATUS response upon
- failure. When the operation is successful, any of the responses may
- be returned (depending on the operation). If no data needs to be
- returned to the client, the SSH_FXP_STATUS response with SSH_FX_OK
- status is appropriate. Otherwise, the SSH_FXP_HANDLE message is used
- to return a file handle (for SSH_FXP_OPEN and SSH_FXP_OPENDIR
- requests), SSH_FXP_DATA is used to return data from SSH_FXP_READ,
- SSH_FXP_NAME is used to return one or more file names from a
- SSH_FXP_READDIR or SSH_FXP_REALPATH request, and SSH_FXP_ATTRS is
- used to return file attributes from SSH_FXP_STAT, SSH_FXP_LSTAT, and
- SSH_FXP_FSTAT requests.
-
- Exactly one response will be returned for each request. Each
- response packet contains a request identifier which can be used to
- match each response with the corresponding request. Note that it is
- legal to have several requests outstanding simultaneously, and the
- server is allowed to send responses to them in a different order from
- the order in which the requests were sent (the result of their
- execution, however, is guaranteed to be as if they had been processed
- one at a time in the order in which the requests were sent).
-
- Response packets are of the same general format as request packets.
- Each response packet begins with the request identifier.
-
- The format of the data portion of the SSH_FXP_STATUS response is as
- follows:
-
- uint32 id
- uint32 error/status code
- string error message (ISO-10646 UTF-8 [RFC-2279])
- string language tag (as defined in [RFC-1766])
-
- where `id' is the request identifier, and `error/status code'
- indicates the result of the requested operation. The value SSH_FX_OK
- indicates success, and all other values indicate failure.
-
-
-
-
-
-
-
-
-
-
-
-
-
-Ylonen & Lehtinen Expires April 1, 2002 [Page 20]
-
-Internet-Draft SSH File Transfer Protocol October 2001
-
-
- Currently, the following values are defined (other values may be
- defined by future versions of this protocol):
-
- #define SSH_FX_OK 0
- #define SSH_FX_EOF 1
- #define SSH_FX_NO_SUCH_FILE 2
- #define SSH_FX_PERMISSION_DENIED 3
- #define SSH_FX_FAILURE 4
- #define SSH_FX_BAD_MESSAGE 5
- #define SSH_FX_NO_CONNECTION 6
- #define SSH_FX_CONNECTION_LOST 7
- #define SSH_FX_OP_UNSUPPORTED 8
-
- SSH_FX_OK
- Indicates successful completion of the operation.
-
- SSH_FX_EOF
- indicates end-of-file condition; for SSH_FX_READ it means that no
- more data is available in the file, and for SSH_FX_READDIR it
- indicates that no more files are contained in the directory.
-
- SSH_FX_NO_SUCH_FILE
- is returned when a reference is made to a file which should exist
- but doesn't.
-
- SSH_FX_PERMISSION_DENIED
- is returned when the authenticated user does not have sufficient
- permissions to perform the operation.
-
- SSH_FX_FAILURE
- is a generic catch-all error message; it should be returned if an
- error occurs for which there is no more specific error code
- defined.
-
- SSH_FX_BAD_MESSAGE
- may be returned if a badly formatted packet or protocol
- incompatibility is detected.
-
- SSH_FX_NO_CONNECTION
- is a pseudo-error which indicates that the client has no
- connection to the server (it can only be generated locally by the
- client, and MUST NOT be returned by servers).
-
- SSH_FX_CONNECTION_LOST
- is a pseudo-error which indicates that the connection to the
- server has been lost (it can only be generated locally by the
- client, and MUST NOT be returned by servers).
-
-
-
-
-Ylonen & Lehtinen Expires April 1, 2002 [Page 21]
-
-Internet-Draft SSH File Transfer Protocol October 2001
-
-
- SSH_FX_OP_UNSUPPORTED
- indicates that an attempt was made to perform an operation which
- is not supported for the server (it may be generated locally by
- the client if e.g. the version number exchange indicates that a
- required feature is not supported by the server, or it may be
- returned by the server if the server does not implement an
- operation).
-
- The SSH_FXP_HANDLE response has the following format:
-
- uint32 id
- string handle
-
- where `id' is the request identifier, and `handle' is an arbitrary
- string that identifies an open file or directory on the server. The
- handle is opaque to the client; the client MUST NOT attempt to
- interpret or modify it in any way. The length of the handle string
- MUST NOT exceed 256 data bytes.
-
- The SSH_FXP_DATA response has the following format:
-
- uint32 id
- string data
-
- where `id' is the request identifier, and `data' is an arbitrary byte
- string containing the requested data. The data string may be at most
- the number of bytes requested in a SSH_FXP_READ request, but may also
- be shorter if end of file is reached or if the read is from something
- other than a regular file.
-
- The SSH_FXP_NAME response has the following format:
-
- uint32 id
- uint32 count
- repeats count times:
- string filename
- string longname
- ATTRS attrs
-
- where `id' is the request identifier, `count' is the number of names
- returned in this response, and the remaining fields repeat `count'
- times (so that all three fields are first included for the first
- file, then for the second file, etc). In the repeated part,
- `filename' is a file name being returned (for SSH_FXP_READDIR, it
- will be a relative name within the directory, without any path
- components; for SSH_FXP_REALPATH it will be an absolute path name),
- `longname' is an expanded format for the file name, similar to what
- is returned by "ls -l" on Unix systems, and `attrs' is the attributes
-
-
-
-Ylonen & Lehtinen Expires April 1, 2002 [Page 22]
-
-Internet-Draft SSH File Transfer Protocol October 2001
-
-
- of the file as described in Section ``File Attributes''.
-
- The format of the `longname' field is unspecified by this protocol.
- It MUST be suitable for use in the output of a directory listing
- command (in fact, the recommended operation for a directory listing
- command is to simply display this data). However, clients SHOULD NOT
- attempt to parse the longname field for file attributes; they SHOULD
- use the attrs field instead.
-
- The recommended format for the longname field is as follows:
-
- -rwxr-xr-x 1 mjos staff 348911 Mar 25 14:29 t-filexfer
- 1234567890 123 12345678 12345678 12345678 123456789012
-
- Here, the first line is sample output, and the second field indicates
- widths of the various fields. Fields are separated by spaces. The
- first field lists file permissions for user, group, and others; the
- second field is link count; the third field is the name of the user
- who owns the file; the fourth field is the name of the group that
- owns the file; the fifth field is the size of the file in bytes; the
- sixth field (which actually may contain spaces, but is fixed to 12
- characters) is the file modification time, and the seventh field is
- the file name. Each field is specified to be a minimum of certain
- number of character positions (indicated by the second line above),
- but may also be longer if the data does not fit in the specified
- length.
-
- The SSH_FXP_ATTRS response has the following format:
-
- uint32 id
- ATTRS attrs
-
- where `id' is the request identifier, and `attrs' is the returned
- file attributes as described in Section ``File Attributes''.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Ylonen & Lehtinen Expires April 1, 2002 [Page 23]
-
-Internet-Draft SSH File Transfer Protocol October 2001
-
-
-8. Vendor-Specific Extensions
-
- The SSH_FXP_EXTENDED request provides a generic extension mechanism
- for adding vendor-specific commands. The request has the following
- format:
-
- uint32 id
- string extended-request
- ... any request-specific data ...
-
- where `id' is the request identifier, and `extended-request' is a
- string of the format "name@domain", where domain is an internet
- domain name of the vendor defining the request. The rest of the
- request is completely vendor-specific, and servers should only
- attempt to interpret it if they recognize the `extended-request'
- name.
-
- The server may respond to such requests using any of the response
- packets defined in Section ``Responses from the Server to the
- Client''. Additionally, the server may also respond with a
- SSH_FXP_EXTENDED_REPLY packet, as defined below. If the server does
- not recognize the `extended-request' name, then the server MUST
- respond with SSH_FXP_STATUS with error/status set to
- SSH_FX_OP_UNSUPPORTED.
-
- The SSH_FXP_EXTENDED_REPLY packet can be used to carry arbitrary
- extension-specific data from the server to the client. It is of the
- following format:
-
- uint32 id
- ... any request-specific data ...
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Ylonen & Lehtinen Expires April 1, 2002 [Page 24]
-
-Internet-Draft SSH File Transfer Protocol October 2001
-
-
-9. Security Considerations
-
- This protocol assumes that it is run over a secure channel and that
- the endpoints of the channel have been authenticated. Thus, this
- protocol assumes that it is externally protected from network-level
- attacks.
-
- This protocol provides file system access to arbitrary files on the
- server (only constrained by the server implementation). It is the
- responsibility of the server implementation to enforce any access
- controls that may be required to limit the access allowed for any
- particular user (the user being authenticated externally to this
- protocol, typically using the SSH User Authentication Protocol [6].
-
- Care must be taken in the server implementation to check the validity
- of received file handle strings. The server should not rely on them
- directly; it MUST check the validity of each handle before relying on
- it.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Ylonen & Lehtinen Expires April 1, 2002 [Page 25]
-
-Internet-Draft SSH File Transfer Protocol October 2001
-
-
-10. Changes from previous protocol versions
-
- The SSH File Transfer Protocol has changed over time, before it's
- standardization. The following is a description of the incompatible
- changes between different versions.
-
-10.1 Changes between versions 3 and 2
-
- o The SSH_FXP_READLINK and SSH_FXP_SYMLINK messages were added.
-
- o The SSH_FXP_EXTENDED and SSH_FXP_EXTENDED_REPLY messages were
- added.
-
- o The SSH_FXP_STATUS message was changed to include fields `error
- message' and `language tag'.
-
-
-10.2 Changes between versions 2 and 1
-
- o The SSH_FXP_RENAME message was added.
-
-
-10.3 Changes between versions 1 and 0
-
- o Implementation changes, no actual protocol changes.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Ylonen & Lehtinen Expires April 1, 2002 [Page 26]
-
-Internet-Draft SSH File Transfer Protocol October 2001
-
-
-11. Trademark Issues
-
- "ssh" is a registered trademark of SSH Communications Security Corp
- in the United States and/or other countries.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Ylonen & Lehtinen Expires April 1, 2002 [Page 27]
-
-Internet-Draft SSH File Transfer Protocol October 2001
-
-
-References
-
- [1] Dierks, T., Allen, C., Treese, W., Karlton, P., Freier, A. and
- P. Kocher, "The TLS Protocol Version 1.0", RFC 2246, January
- 1999.
-
- [2] Institute of Electrical and Electronics Engineers, "Information
- Technology - Portable Operating System Interface (POSIX) - Part
- 1: System Application Program Interface (API) [C Language]",
- IEEE Standard 1003.2, 1996.
-
- [3] Rinne, T., Ylonen, T., Kivinen, T., Saarinen, M. and S.
- Lehtinen, "SSH Protocol Architecture", draft-ietf-secsh-
- architecture-09 (work in progress), July 2001.
-
- [4] Rinne, T., Ylonen, T., Kivinen, T., Saarinen, M. and S.
- Lehtinen, "SSH Protocol Transport Protocol", draft-ietf-secsh-
- architecture-09 (work in progress), July 2001.
-
- [5] Rinne, T., Ylonen, T., Kivinen, T., Saarinen, M. and S.
- Lehtinen, "SSH Connection Protocol", draft-ietf-secsh-connect-11
- (work in progress), July 2001.
-
- [6] Rinne, T., Ylonen, T., Kivinen, T., Saarinen, M. and S.
- Lehtinen, "SSH Authentication Protocol", draft-ietf-secsh-
- userauth-11 (work in progress), July 2001.
-
-
-Authors' Addresses
-
- Tatu Ylonen
- SSH Communications Security Corp
- Fredrikinkatu 42
- HELSINKI FIN-00100
- Finland
-
-
-
- Sami Lehtinen
- SSH Communications Security Corp
- Fredrikinkatu 42
- HELSINKI FIN-00100
- Finland
-
-
-
-
-
-
-Ylonen & Lehtinen Expires April 1, 2002 [Page 28]
-
-Internet-Draft SSH File Transfer Protocol October 2001
-
-
-Full Copyright Statement
-
- Copyright (C) The Internet Society (2001). All Rights Reserved.
-
- This document and translations of it may be copied and furnished to
- others, and derivative works that comment on or otherwise explain it
- or assist in its implementation may be prepared, copied, published
- and distributed, in whole or in part, without restriction of any
- kind, provided that the above copyright notice and this paragraph are
- included on all such copies and derivative works. However, this
- document itself may not be modified in any way, such as by removing
- the copyright notice or references to the Internet Society or other
- Internet organizations, except as needed for the purpose of
- developing Internet standards in which case the procedures for
- copyrights defined in the Internet Standards process must be
- followed, or as required to translate it into languages other than
- English.
-
- The limited permissions granted above are perpetual and will not be
- revoked by the Internet Society or its successors or assigns.
-
- This document and the information contained herein is provided on an
- "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
- TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
- BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
- HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
- MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
-
-Acknowledgement
-
- Funding for the RFC Editor function is currently provided by the
- Internet Society.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Ylonen & Lehtinen Expires April 1, 2002 [Page 29]
-
-
-
diff --git a/lib/ssh/doc/standard/draft-ietf-secsh-filexfer-03.2.ps b/lib/ssh/doc/standard/draft-ietf-secsh-filexfer-03.2.ps
deleted file mode 100644
index 6a40cd6067..0000000000
--- a/lib/ssh/doc/standard/draft-ietf-secsh-filexfer-03.2.ps
+++ /dev/null
@@ -1,3511 +0,0 @@
-%!PS-Adobe-3.0
-%%BoundingBox: 75 0 595 747
-%%Title: Enscript Output
-%%For: Magnus Thoang
-%%Creator: GNU enscript 1.6.1
-%%CreationDate: Wed Nov 12 12:18:50 2003
-%%Orientation: Portrait
-%%Pages: 18 0
-%%DocumentMedia: A4 595 842 0 () ()
-%%DocumentNeededResources: (atend)
-%%EndComments
-%%BeginProlog
-%%BeginProcSet: PStoPS 1 15
-userdict begin
-[/showpage/erasepage/copypage]{dup where{pop dup load
- type/operatortype eq{1 array cvx dup 0 3 index cvx put
- bind def}{pop}ifelse}{pop}ifelse}forall
-[/letter/legal/executivepage/a4/a4small/b5/com10envelope
- /monarchenvelope/c5envelope/dlenvelope/lettersmall/note
- /folio/quarto/a5]{dup where{dup wcheck{exch{}put}
- {pop{}def}ifelse}{pop}ifelse}forall
-/setpagedevice {pop}bind 1 index where{dup wcheck{3 1 roll put}
- {pop def}ifelse}{def}ifelse
-/PStoPSmatrix matrix currentmatrix def
-/PStoPSxform matrix def/PStoPSclip{clippath}def
-/defaultmatrix{PStoPSmatrix exch PStoPSxform exch concatmatrix}bind def
-/initmatrix{matrix defaultmatrix setmatrix}bind def
-/initclip[{matrix currentmatrix PStoPSmatrix setmatrix
- [{currentpoint}stopped{$error/newerror false put{newpath}}
- {/newpath cvx 3 1 roll/moveto cvx 4 array astore cvx}ifelse]
- {[/newpath cvx{/moveto cvx}{/lineto cvx}
- {/curveto cvx}{/closepath cvx}pathforall]cvx exch pop}
- stopped{$error/errorname get/invalidaccess eq{cleartomark
- $error/newerror false put cvx exec}{stop}ifelse}if}bind aload pop
- /initclip dup load dup type dup/operatortype eq{pop exch pop}
- {dup/arraytype eq exch/packedarraytype eq or
- {dup xcheck{exch pop aload pop}{pop cvx}ifelse}
- {pop cvx}ifelse}ifelse
- {newpath PStoPSclip clip newpath exec setmatrix} bind aload pop]cvx def
-/initgraphics{initmatrix newpath initclip 1 setlinewidth
- 0 setlinecap 0 setlinejoin []0 setdash 0 setgray
- 10 setmiterlimit}bind def
-end
-%%EndProcSet
-%%BeginResource: procset Enscript-Prolog 1.6 1
-%
-% Procedures.
-%
-
-/_S { % save current state
- /_s save def
-} def
-/_R { % restore from saved state
- _s restore
-} def
-
-/S { % showpage protecting gstate
- gsave
- showpage
- grestore
-} bind def
-
-/MF { % fontname newfontname -> - make a new encoded font
- /newfontname exch def
- /fontname exch def
-
- /fontdict fontname findfont def
- /newfont fontdict maxlength dict def
-
- fontdict {
- exch
- dup /FID eq {
- % skip FID pair
- pop pop
- } {
- % copy to the new font dictionary
- exch newfont 3 1 roll put
- } ifelse
- } forall
-
- newfont /FontName newfontname put
-
- % insert only valid encoding vectors
- encoding_vector length 256 eq {
- newfont /Encoding encoding_vector put
- } if
-
- newfontname newfont definefont pop
-} def
-
-/SF { % fontname width height -> - set a new font
- /height exch def
- /width exch def
-
- findfont
- [width 0 0 height 0 0] makefont setfont
-} def
-
-/SUF { % fontname width height -> - set a new user font
- /height exch def
- /width exch def
-
- /F-gs-user-font MF
- /F-gs-user-font width height SF
-} def
-
-/M {moveto} bind def
-/s {show} bind def
-
-/Box { % x y w h -> - define box path
- /d_h exch def /d_w exch def /d_y exch def /d_x exch def
- d_x d_y moveto
- d_w 0 rlineto
- 0 d_h rlineto
- d_w neg 0 rlineto
- closepath
-} def
-
-/bgs { % x y height blskip gray str -> - show string with bg color
- /str exch def
- /gray exch def
- /blskip exch def
- /height exch def
- /y exch def
- /x exch def
-
- gsave
- x y blskip sub str stringwidth pop height Box
- gray setgray
- fill
- grestore
- x y M str s
-} def
-
-% Highlight bars.
-/highlight_bars { % nlines lineheight output_y_margin gray -> -
- gsave
- setgray
- /ymarg exch def
- /lineheight exch def
- /nlines exch def
-
- % This 2 is just a magic number to sync highlight lines to text.
- 0 d_header_y ymarg sub 2 sub translate
-
- /cw d_output_w cols div def
- /nrows d_output_h ymarg 2 mul sub lineheight div cvi def
-
- % for each column
- 0 1 cols 1 sub {
- cw mul /xp exch def
-
- % for each rows
- 0 1 nrows 1 sub {
- /rn exch def
- rn lineheight mul neg /yp exch def
- rn nlines idiv 2 mod 0 eq {
- % Draw highlight bar. 4 is just a magic indentation.
- xp 4 add yp cw 8 sub lineheight neg Box fill
- } if
- } for
- } for
-
- grestore
-} def
-
-% Line highlight bar.
-/line_highlight { % x y width height gray -> -
- gsave
- /gray exch def
- Box gray setgray fill
- grestore
-} def
-
-% Column separator lines.
-/column_lines {
- gsave
- .1 setlinewidth
- 0 d_footer_h translate
- /cw d_output_w cols div def
- 1 1 cols 1 sub {
- cw mul 0 moveto
- 0 d_output_h rlineto stroke
- } for
- grestore
-} def
-
-% Column borders.
-/column_borders {
- gsave
- .1 setlinewidth
- 0 d_footer_h moveto
- 0 d_output_h rlineto
- d_output_w 0 rlineto
- 0 d_output_h neg rlineto
- closepath stroke
- grestore
-} def
-
-% Do the actual underlay drawing
-/draw_underlay {
- ul_style 0 eq {
- ul_str true charpath stroke
- } {
- ul_str show
- } ifelse
-} def
-
-% Underlay
-/underlay { % - -> -
- gsave
- 0 d_page_h translate
- d_page_h neg d_page_w atan rotate
-
- ul_gray setgray
- ul_font setfont
- /dw d_page_h dup mul d_page_w dup mul add sqrt def
- ul_str stringwidth pop dw exch sub 2 div ul_h_ptsize -2 div moveto
- draw_underlay
- grestore
-} def
-
-/user_underlay { % - -> -
- gsave
- ul_x ul_y translate
- ul_angle rotate
- ul_gray setgray
- ul_font setfont
- 0 0 ul_h_ptsize 2 div sub moveto
- draw_underlay
- grestore
-} def
-
-% Page prefeed
-/page_prefeed { % bool -> -
- statusdict /prefeed known {
- statusdict exch /prefeed exch put
- } {
- pop
- } ifelse
-} def
-
-% Wrapped line markers
-/wrapped_line_mark { % x y charwith charheight type -> -
- /type exch def
- /h exch def
- /w exch def
- /y exch def
- /x exch def
-
- type 2 eq {
- % Black boxes (like TeX does)
- gsave
- 0 setlinewidth
- x w 4 div add y M
- 0 h rlineto w 2 div 0 rlineto 0 h neg rlineto
- closepath fill
- grestore
- } {
- type 3 eq {
- % Small arrows
- gsave
- .2 setlinewidth
- x w 2 div add y h 2 div add M
- w 4 div 0 rlineto
- x w 4 div add y lineto stroke
-
- x w 4 div add w 8 div add y h 4 div add M
- x w 4 div add y lineto
- w 4 div h 8 div rlineto stroke
- grestore
- } {
- % do nothing
- } ifelse
- } ifelse
-} def
-
-% EPSF import.
-
-/BeginEPSF {
- /b4_Inc_state save def % Save state for cleanup
- /dict_count countdictstack def % Count objects on dict stack
- /op_count count 1 sub def % Count objects on operand stack
- userdict begin
- /showpage { } def
- 0 setgray 0 setlinecap
- 1 setlinewidth 0 setlinejoin
- 10 setmiterlimit [ ] 0 setdash newpath
- /languagelevel where {
- pop languagelevel
- 1 ne {
- false setstrokeadjust false setoverprint
- } if
- } if
-} bind def
-
-/EndEPSF {
- count op_count sub { pos } repeat % Clean up stacks
- countdictstack dict_count sub { end } repeat
- b4_Inc_state restore
-} bind def
-
-% Check PostScript language level.
-/languagelevel where {
- pop /gs_languagelevel languagelevel def
-} {
- /gs_languagelevel 1 def
-} ifelse
-%%EndResource
-%%BeginResource: procset Enscript-Encoding-88591 1.6 1
-/encoding_vector [
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/space /exclam /quotedbl /numbersign
-/dollar /percent /ampersand /quoteright
-/parenleft /parenright /asterisk /plus
-/comma /hyphen /period /slash
-/zero /one /two /three
-/four /five /six /seven
-/eight /nine /colon /semicolon
-/less /equal /greater /question
-/at /A /B /C
-/D /E /F /G
-/H /I /J /K
-/L /M /N /O
-/P /Q /R /S
-/T /U /V /W
-/X /Y /Z /bracketleft
-/backslash /bracketright /asciicircum /underscore
-/quoteleft /a /b /c
-/d /e /f /g
-/h /i /j /k
-/l /m /n /o
-/p /q /r /s
-/t /u /v /w
-/x /y /z /braceleft
-/bar /braceright /tilde /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/space /exclamdown /cent /sterling
-/currency /yen /brokenbar /section
-/dieresis /copyright /ordfeminine /guillemotleft
-/logicalnot /hyphen /registered /macron
-/degree /plusminus /twosuperior /threesuperior
-/acute /mu /paragraph /bullet
-/cedilla /onesuperior /ordmasculine /guillemotright
-/onequarter /onehalf /threequarters /questiondown
-/Agrave /Aacute /Acircumflex /Atilde
-/Adieresis /Aring /AE /Ccedilla
-/Egrave /Eacute /Ecircumflex /Edieresis
-/Igrave /Iacute /Icircumflex /Idieresis
-/Eth /Ntilde /Ograve /Oacute
-/Ocircumflex /Otilde /Odieresis /multiply
-/Oslash /Ugrave /Uacute /Ucircumflex
-/Udieresis /Yacute /Thorn /germandbls
-/agrave /aacute /acircumflex /atilde
-/adieresis /aring /ae /ccedilla
-/egrave /eacute /ecircumflex /edieresis
-/igrave /iacute /icircumflex /idieresis
-/eth /ntilde /ograve /oacute
-/ocircumflex /otilde /odieresis /divide
-/oslash /ugrave /uacute /ucircumflex
-/udieresis /yacute /thorn /ydieresis
-] def
-%%EndResource
-%%EndProlog
-%%BeginSetup
-%%IncludeResource: font Courier-Bold
-%%IncludeResource: font Courier
-/HFpt_w 10 def
-/HFpt_h 10 def
-/Courier-Bold /HF-gs-font MF
-/HF /HF-gs-font findfont [HFpt_w 0 0 HFpt_h 0 0] makefont def
-/Courier /F-gs-font MF
-/F-gs-font 10 10 SF
-/#copies 1 def
-/d_page_w 520 def
-/d_page_h 747 def
-/d_header_x 0 def
-/d_header_y 747 def
-/d_header_w 520 def
-/d_header_h 0 def
-/d_footer_x 0 def
-/d_footer_y 0 def
-/d_footer_w 520 def
-/d_footer_h 0 def
-/d_output_w 520 def
-/d_output_h 747 def
-/cols 1 def
-userdict/PStoPSxform PStoPSmatrix matrix currentmatrix
- matrix invertmatrix matrix concatmatrix
- matrix invertmatrix put
-%%EndSetup
-%%Page: (0,1) 1
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 1 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 701 M
-(Secure Shell Working Group J. Galbraith) s
-5 690 M
-(Internet-Draft VanDyke Software) s
-5 679 M
-(Expires: April 16, 2003 T. Ylonen) s
-5 668 M
-( S. Lehtinen) s
-5 657 M
-( SSH Communications Security Corp) s
-5 646 M
-( October 16, 2002) s
-5 613 M
-( SSH File Transfer Protocol) s
-5 602 M
-( draft-ietf-secsh-filexfer-03.txt) s
-5 580 M
-(Status of this Memo) s
-5 558 M
-( This document is an Internet-Draft and is in full conformance with) s
-5 547 M
-( all provisions of Section 10 of RFC2026.) s
-5 525 M
-( Internet-Drafts are working documents of the Internet Engineering) s
-5 514 M
-( Task Force \(IETF\), its areas, and its working groups. Note that) s
-5 503 M
-( other groups may also distribute working documents as Internet-) s
-5 492 M
-( Drafts.) s
-5 470 M
-( Internet-Drafts are draft documents valid for a maximum of six months) s
-5 459 M
-( and may be updated, replaced, or obsoleted by other documents at any) s
-5 448 M
-( time. It is inappropriate to use Internet-Drafts as reference) s
-5 437 M
-( material or to cite them other than as "work in progress.") s
-5 415 M
-( The list of current Internet-Drafts can be accessed at http://) s
-5 404 M
-( www.ietf.org/ietf/1id-abstracts.txt.) s
-5 382 M
-( The list of Internet-Draft Shadow Directories can be accessed at) s
-5 371 M
-( http://www.ietf.org/shadow.html.) s
-5 349 M
-( This Internet-Draft will expire on April 16, 2003.) s
-5 327 M
-(Copyright Notice) s
-5 305 M
-( Copyright \(C\) The Internet Society \(2002\). All Rights Reserved.) s
-5 283 M
-(Abstract) s
-5 261 M
-( The SSH File Transfer Protocol provides secure file transfer) s
-5 250 M
-( functionality over any reliable data stream. It is the standard file) s
-5 239 M
-( transfer protocol for use with the SSH2 protocol. This document) s
-5 228 M
-( describes the file transfer protocol and its interface to the SSH2) s
-5 217 M
-( protocol suite.) s
-5 129 M
-(Galbraith, et al. Expires April 16, 2003 [Page 1]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 2 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH File Transfer Protocol October 2002) s
-5 690 M
-(Table of Contents) s
-5 668 M
-( 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . 3) s
-5 657 M
-( 2. Use with the SSH Connection Protocol . . . . . . . . . . . 4) s
-5 646 M
-( 3. General Packet Format . . . . . . . . . . . . . . . . . . 5) s
-5 635 M
-( 4. Protocol Initialization . . . . . . . . . . . . . . . . . 7) s
-5 624 M
-( 4.1 Client Initialization . . . . . . . . . . . . . . . . . . 7) s
-5 613 M
-( 4.2 Server Initialization . . . . . . . . . . . . . . . . . . 7) s
-5 602 M
-( 4.3 Determining Server Newline Convention . . . . . . . . . . 8) s
-5 591 M
-( 5. File Attributes . . . . . . . . . . . . . . . . . . . . . 9) s
-5 580 M
-( 5.1 Flags . . . . . . . . . . . . . . . . . . . . . . . . . . 9) s
-5 569 M
-( 5.2 Type . . . . . . . . . . . . . . . . . . . . . . . . . . . 10) s
-5 558 M
-( 5.3 Size . . . . . . . . . . . . . . . . . . . . . . . . . . . 10) s
-5 547 M
-( 5.4 Owner and Group . . . . . . . . . . . . . . . . . . . . . 10) s
-5 536 M
-( 5.5 Permissions . . . . . . . . . . . . . . . . . . . . . . . 11) s
-5 525 M
-( 5.6 Times . . . . . . . . . . . . . . . . . . . . . . . . . . 11) s
-5 514 M
-( 5.7 ACL . . . . . . . . . . . . . . . . . . . . . . . . . . . 11) s
-5 503 M
-( 5.8 Extended attributes . . . . . . . . . . . . . . . . . . . 12) s
-5 492 M
-( 6. Requests From the Client to the Server . . . . . . . . . . 13) s
-5 481 M
-( 6.1 Request Synchronization and Reordering . . . . . . . . . . 13) s
-5 470 M
-( 6.2 File Names . . . . . . . . . . . . . . . . . . . . . . . . 14) s
-5 459 M
-( 6.3 Opening, Creating, and Closing Files . . . . . . . . . . . 14) s
-5 448 M
-( 6.4 Reading and Writing . . . . . . . . . . . . . . . . . . . 17) s
-5 437 M
-( 6.5 Removing and Renaming Files . . . . . . . . . . . . . . . 18) s
-5 426 M
-( 6.6 Creating and Deleting Directories . . . . . . . . . . . . 19) s
-5 415 M
-( 6.7 Scanning Directories . . . . . . . . . . . . . . . . . . . 19) s
-5 404 M
-( 6.8 Retrieving File Attributes . . . . . . . . . . . . . . . . 20) s
-5 393 M
-( 6.9 Setting File Attributes . . . . . . . . . . . . . . . . . 21) s
-5 382 M
-( 6.10 Dealing with Symbolic links . . . . . . . . . . . . . . . 22) s
-5 371 M
-( 6.11 Canonicalizing the Server-Side Path Name . . . . . . . . . 23) s
-5 360 M
-( 6.11.1 Best practice for dealing with paths . . . . . . . . . . . 23) s
-5 349 M
-( 7. Responses from the Server to the Client . . . . . . . . . 24) s
-5 338 M
-( 8. Vendor-Specific Extensions . . . . . . . . . . . . . . . . 28) s
-5 327 M
-( 9. Security Considerations . . . . . . . . . . . . . . . . . 29) s
-5 316 M
-( 10. Changes from previous protocol versions . . . . . . . . . 30) s
-5 305 M
-( 10.1 Changes between versions 4 and 3 . . . . . . . . . . . . . 30) s
-5 294 M
-( 10.2 Changes between versions 3 and 2 . . . . . . . . . . . . . 31) s
-5 283 M
-( 10.3 Changes between versions 2 and 1 . . . . . . . . . . . . . 31) s
-5 272 M
-( 10.4 Changes between versions 1 and 0 . . . . . . . . . . . . . 31) s
-5 261 M
-( 11. Trademark Issues . . . . . . . . . . . . . . . . . . . . . 32) s
-5 250 M
-( References . . . . . . . . . . . . . . . . . . . . . . . . 33) s
-5 239 M
-( Authors' Addresses . . . . . . . . . . . . . . . . . . . . 33) s
-5 228 M
-( Full Copyright Statement . . . . . . . . . . . . . . . . . 35) s
-5 129 M
-(Galbraith, et al. Expires April 16, 2003 [Page 2]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (2,3) 2
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 3 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH File Transfer Protocol October 2002) s
-5 690 M
-(1. Introduction) s
-5 668 M
-( This protocol provides secure file transfer \(and more generally file) s
-5 657 M
-( system access\) functionality over a reliable data stream, such as a) s
-5 646 M
-( channel in the SSH2 protocol [5].) s
-5 624 M
-( This protocol is designed so that it could be used to implement a) s
-5 613 M
-( secure remote file system service, as well as a secure file transfer) s
-5 602 M
-( service.) s
-5 580 M
-( This protocol assumes that it runs over a secure channel, and that) s
-5 569 M
-( the server has already authenticated the user at the client end, and) s
-5 558 M
-( that the identity of the client user is externally available to the) s
-5 547 M
-( server implementation.) s
-5 525 M
-( In general, this protocol follows a simple request-response model.) s
-5 514 M
-( Each request and response contains a sequence number and multiple) s
-5 503 M
-( requests may be pending simultaneously. There are a relatively large) s
-5 492 M
-( number of different request messages, but a small number of possible) s
-5 481 M
-( response messages. Each request has one or more response messages) s
-5 470 M
-( that may be returned in result \(e.g., a read either returns data or) s
-5 459 M
-( reports error status\).) s
-5 437 M
-( The packet format descriptions in this specification follow the) s
-5 426 M
-( notation presented in the secsh architecture draft. [5]) s
-5 404 M
-( Even though this protocol is described in the context of the SSH2) s
-5 393 M
-( protocol, this protocol is general and independent of the rest of the) s
-5 382 M
-( SSH2 protocol suite. It could be used in a number of different) s
-5 371 M
-( applications, such as secure file transfer over TLS RFC 2246 [1] and) s
-5 360 M
-( transfer of management information in VPN applications.) s
-5 129 M
-(Galbraith, et al. Expires April 16, 2003 [Page 3]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 4 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH File Transfer Protocol October 2002) s
-5 690 M
-(2. Use with the SSH Connection Protocol) s
-5 668 M
-( When used with the SSH2 Protocol suite, this protocol is intended to) s
-5 657 M
-( be used from the SSH Connection Protocol [7] as a subsystem, as) s
-5 646 M
-( described in section ``Starting a Shell or a Command''. The) s
-5 635 M
-( subsystem name used with this protocol is "sftp".) s
-5 129 M
-(Galbraith, et al. Expires April 16, 2003 [Page 4]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (4,5) 3
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 5 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH File Transfer Protocol October 2002) s
-5 690 M
-(3. General Packet Format) s
-5 668 M
-( All packets transmitted over the secure connection are of the) s
-5 657 M
-( following format:) s
-5 635 M
-( uint32 length) s
-5 624 M
-( byte type) s
-5 613 M
-( byte[length - 1] data payload) s
-5 591 M
-( That is, they are just data preceded by 32-bit length and 8-bit type) s
-5 580 M
-( fields. The `length' is the length of the data area, and does not) s
-5 569 M
-( include the `length' field itself. The format and interpretation of) s
-5 558 M
-( the data area depends on the packet type.) s
-5 536 M
-( All packet descriptions below only specify the packet type and the) s
-5 525 M
-( data that goes into the data field. Thus, they should be prefixed by) s
-5 514 M
-( the `length' and `type' fields.) s
-5 492 M
-( The maximum size of a packet is in practice determined by the client) s
-5 481 M
-( \(the maximum size of read or write requests that it sends, plus a few) s
-5 470 M
-( bytes of packet overhead\). All servers SHOULD support packets of at) s
-5 459 M
-( least 34000 bytes \(where the packet size refers to the full length,) s
-5 448 M
-( including the header above\). This should allow for reads and writes) s
-5 437 M
-( of at most 32768 bytes.) s
-5 415 M
-( There is no limit on the number of outstanding \(non-acknowledged\)) s
-5 404 M
-( requests that the client may send to the server. In practice this is) s
-5 393 M
-( limited by the buffering available on the data stream and the queuing) s
-5 382 M
-( performed by the server. If the server's queues are full, it should) s
-5 371 M
-( not read any more data from the stream, and flow control will prevent) s
-5 360 M
-( the client from sending more requests. Note, however, that while) s
-5 349 M
-( there is no restriction on the protocol level, the client's API may) s
-5 338 M
-( provide a limit in order to prevent infinite queuing of outgoing) s
-5 327 M
-( requests at the client.) s
-5 305 M
-( The following values are defined for packet types.) s
-5 129 M
-(Galbraith, et al. Expires April 16, 2003 [Page 5]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 6 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH File Transfer Protocol October 2002) s
-5 690 M
-( #define SSH_FXP_INIT 1) s
-5 679 M
-( #define SSH_FXP_VERSION 2) s
-5 668 M
-( #define SSH_FXP_OPEN 3) s
-5 657 M
-( #define SSH_FXP_CLOSE 4) s
-5 646 M
-( #define SSH_FXP_READ 5) s
-5 635 M
-( #define SSH_FXP_WRITE 6) s
-5 624 M
-( #define SSH_FXP_LSTAT 7) s
-5 613 M
-( #define SSH_FXP_FSTAT 8) s
-5 602 M
-( #define SSH_FXP_SETSTAT 9) s
-5 591 M
-( #define SSH_FXP_FSETSTAT 10) s
-5 580 M
-( #define SSH_FXP_OPENDIR 11) s
-5 569 M
-( #define SSH_FXP_READDIR 12) s
-5 558 M
-( #define SSH_FXP_REMOVE 13) s
-5 547 M
-( #define SSH_FXP_MKDIR 14) s
-5 536 M
-( #define SSH_FXP_RMDIR 15) s
-5 525 M
-( #define SSH_FXP_REALPATH 16) s
-5 514 M
-( #define SSH_FXP_STAT 17) s
-5 503 M
-( #define SSH_FXP_RENAME 18) s
-5 492 M
-( #define SSH_FXP_READLINK 19) s
-5 481 M
-( #define SSH_FXP_SYMLINK 20) s
-5 459 M
-( #define SSH_FXP_STATUS 101) s
-5 448 M
-( #define SSH_FXP_HANDLE 102) s
-5 437 M
-( #define SSH_FXP_DATA 103) s
-5 426 M
-( #define SSH_FXP_NAME 104) s
-5 415 M
-( #define SSH_FXP_ATTRS 105) s
-5 393 M
-( #define SSH_FXP_EXTENDED 200) s
-5 382 M
-( #define SSH_FXP_EXTENDED_REPLY 201) s
-5 360 M
-( RESERVED_FOR_EXTENSIONS 210-255) s
-5 338 M
-( Additional packet types should only be defined if the protocol) s
-5 327 M
-( version number \(see Section ``Protocol Initialization''\) is) s
-5 316 M
-( incremented, and their use MUST be negotiated using the version) s
-5 305 M
-( number. However, the SSH_FXP_EXTENDED and SSH_FXP_EXTENDED_REPLY) s
-5 294 M
-( packets can be used to implement vendor-specific extensions. See) s
-5 283 M
-( Section ``Vendor-Specific-Extensions'' for more details.) s
-5 129 M
-(Galbraith, et al. Expires April 16, 2003 [Page 6]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (6,7) 4
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 7 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH File Transfer Protocol October 2002) s
-5 690 M
-(4. Protocol Initialization) s
-5 668 M
-( When the file transfer protocol starts, the client first sends a) s
-5 657 M
-( SSH_FXP_INIT \(including its version number\) packet to the server.) s
-5 646 M
-( The server responds with a SSH_FXP_VERSION packet, supplying the) s
-5 635 M
-( lowest of its own and the client's version number. Both parties) s
-5 624 M
-( should from then on adhere to particular version of the protocol.) s
-5 602 M
-( The version number of the protocol specified in this document is 4.) s
-5 591 M
-( The version number should be incremented for each incompatible) s
-5 580 M
-( revision of this protocol.) s
-5 558 M
-(4.1 Client Initialization) s
-5 536 M
-( The SSH_FXP_INIT packet \(from client to server\) has the following) s
-5 525 M
-( data:) s
-5 503 M
-( uint32 version) s
-5 481 M
-( Version 3 of this protocol allowed clients to include extensions in) s
-5 470 M
-( the SSH_FXP_INIT packet; however, this can cause interoperability) s
-5 459 M
-( problems with version 1 and version 2 servers because the client must) s
-5 448 M
-( send this packet before knowing the servers version.) s
-5 426 M
-( In this version of the protocol, clients MUST use the) s
-5 415 M
-( SSH_FXP_EXTENDED packet to send extensions to the server after) s
-5 404 M
-( version exchange has completed. Clients MUST NOT include extensions) s
-5 393 M
-( in the version packet. This will prevent interoperability problems) s
-5 382 M
-( with older servers) s
-5 360 M
-(4.2 Server Initialization) s
-5 338 M
-( The SSH_FXP_VERSION packet \(from server to client\) has the following) s
-5 327 M
-( data:) s
-5 305 M
-( uint32 version) s
-5 294 M
-( <extension data>) s
-5 272 M
-( 'version' is the lower of the protocol version supported by the) s
-5 261 M
-( server and the version number received from the client.) s
-5 239 M
-( The extension data may be empty, or may be a sequence of) s
-5 217 M
-( string extension_name) s
-5 206 M
-( string extension_data) s
-5 184 M
-( pairs \(both strings MUST always be present if one is, but the) s
-5 173 M
-( `extension_data' string may be of zero length\). If present, these) s
-5 129 M
-(Galbraith, et al. Expires April 16, 2003 [Page 7]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 8 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH File Transfer Protocol October 2002) s
-5 690 M
-( strings indicate extensions to the baseline protocol. The) s
-5 679 M
-( `extension_name' field\(s\) identify the name of the extension. The) s
-5 668 M
-( name should be of the form "name@domain", where the domain is the DNS) s
-5 657 M
-( domain name of the organization defining the extension. Additional) s
-5 646 M
-( names that are not of this format may be defined later by the IETF.) s
-5 635 M
-( Implementations MUST silently ignore any extensions whose name they) s
-5 624 M
-( do not recognize.) s
-5 602 M
-(4.3 Determining Server Newline Convention) s
-5 580 M
-( In order to correctly process text files in a cross platform) s
-5 569 M
-( compatible way, the newline convention must be converted from that of) s
-5 558 M
-( the server to that of the client, or, during an upload, from that of) s
-5 547 M
-( the client to that of the server.) s
-5 525 M
-( Versions 3 and prior of this protocol made no provisions for) s
-5 514 M
-( processing text files. Many clients implemented some sort of) s
-5 503 M
-( conversion algorithm, but without either a 'canonical' on the wire) s
-5 492 M
-( format or knowledge of the servers newline convention, correct) s
-5 481 M
-( conversion was not always possible.) s
-5 459 M
-( Starting with Version 4, the SSH_FXF_TEXT file open flag \(Section) s
-5 448 M
-( 6.3\) makes it possible to request that the server translate a file to) s
-5 437 M
-( a 'canonical' on the wire format. This format uses \\r\\n as the line) s
-5 426 M
-( separator.) s
-5 404 M
-( Servers for systems using multiple newline characters \(for example,) s
-5 393 M
-( Mac OS X or VMS\) or systems using counted records, MUST translate to) s
-5 382 M
-( the canonical form.) s
-5 360 M
-( However, to ease the burden of implementation on servers that use a) s
-5 349 M
-( single, simple separator sequence, the following extension allows the) s
-5 338 M
-( canonical format to be changed.) s
-5 316 M
-( string "newline") s
-5 305 M
-( string new-canonical-separator \(usually "\\r" or "\\n" or "\\r\\n"\)) s
-5 283 M
-( All clients MUST support this extension.) s
-5 261 M
-( When processing text files, clients SHOULD NOT translate any) s
-5 250 M
-( character or sequence that is not an exact match of the servers) s
-5 239 M
-( newline separator.) s
-5 217 M
-( In particular, if the newline sequence being used is the canonical) s
-5 206 M
-( "\\r\\n" sequence, a lone \\r or a lone \\n SHOULD be written through) s
-5 195 M
-( without change.) s
-5 129 M
-(Galbraith, et al. Expires April 16, 2003 [Page 8]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (8,9) 5
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 9 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH File Transfer Protocol October 2002) s
-5 690 M
-(5. File Attributes) s
-5 668 M
-( A new compound data type is defined for encoding file attributes.) s
-5 657 M
-( The same encoding is used both when returning file attributes from) s
-5 646 M
-( the server and when sending file attributes to the server. When) s
-5 635 M
-( sending it to the server, the flags field specifies which attributes) s
-5 624 M
-( are included, and the server will use default values for the) s
-5 613 M
-( remaining attributes \(or will not modify the values of remaining) s
-5 602 M
-( attributes\). When receiving attributes from the server, the flags) s
-5 591 M
-( specify which attributes are included in the returned data. The) s
-5 580 M
-( server normally returns all attributes it knows about.) s
-5 558 M
-( uint32 flags) s
-5 547 M
-( byte type always present) s
-5 536 M
-( uint64 size present only if flag SSH_FILEXFER_ATTR_SIZE) s
-5 525 M
-( string owner present only if flag SSH_FILEXFER_ATTR_OWNERGROUP) s
-5 514 M
-( string group present only if flag SSH_FILEXFER_ATTR_OWNERGROUP) s
-5 503 M
-( uint32 permissions present only if flag SSH_FILEXFER_ATTR_PERMISSIONS) s
-5 492 M
-( uint32 atime present only if flag SSH_FILEXFER_ATTR_ACCESSTIME) s
-5 481 M
-( uint32 createtime present only if flag SSH_FILEXFER_ATTR_CREATETIME) s
-5 470 M
-( uint32 mtime present only if flag SSH_FILEXFER_ATTR_MODIFYTIME) s
-5 459 M
-( string acl present only if flag SSH_FILEXFER_ATTR_ACL) s
-5 448 M
-( uint32 extended_count present only if flag SSH_FILEXFER_ATTR_EXTENDED) s
-5 437 M
-( string extended_type) s
-5 426 M
-( string extended_data) s
-5 415 M
-( ... more extended data \(extended_type - extended_data pairs\),) s
-5 404 M
-( so that number of pairs equals extended_count) s
-5 371 M
-(5.1 Flags) s
-5 349 M
-( The `flags' specify which of the fields are present. Those fields) s
-5 338 M
-( for which the corresponding flag is not set are not present \(not) s
-5 327 M
-( included in the packet\). New flags can only be added by incrementing) s
-5 316 M
-( the protocol version number \(or by using the extension mechanism) s
-5 305 M
-( described below\).) s
-5 283 M
-( The flags bits are defined to have the following values:) s
-5 261 M
-( #define SSH_FILEXFER_ATTR_SIZE 0x00000001) s
-5 250 M
-( #define SSH_FILEXFER_ATTR_PERMISSIONS 0x00000004) s
-5 239 M
-( #define SSH_FILEXFER_ATTR_ACCESSTIME 0x00000008) s
-5 228 M
-( #define SSH_FILEXFER_ATTR_CREATETIME 0x00000010) s
-5 217 M
-( #define SSH_FILEXFER_ATTR_MODIFYTIME 0x00000020) s
-5 206 M
-( #define SSH_FILEXFER_ATTR_ACL 0x00000040) s
-5 195 M
-( #define SSH_FILEXFER_ATTR_OWNERGROUP 0x00000080) s
-5 184 M
-( #define SSH_FILEXFER_ATTR_EXTENDED 0x80000000) s
-5 129 M
-(Galbraith, et al. Expires April 16, 2003 [Page 9]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 10 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH File Transfer Protocol October 2002) s
-5 690 M
-( In previous versions of this protocol flags value 0x00000002 was) s
-5 679 M
-( SSH_FILEXFER_ATTR_UIDGID. This value is now unused, and OWNERGROUP) s
-5 668 M
-( was given a new value in order to ease implementation burden.) s
-5 657 M
-( 0x00000002 MUST NOT appear in the mask. Some future version of this) s
-5 646 M
-( protocol may reuse flag 0x00000002.) s
-5 624 M
-(5.2 Type) s
-5 602 M
-( The type field is always present. The following types are defined:) s
-5 580 M
-( #define SSH_FILEXFER_TYPE_REGULAR 1) s
-5 569 M
-( #define SSH_FILEXFER_TYPE_DIRECTORY 2) s
-5 558 M
-( #define SSH_FILEXFER_TYPE_SYMLINK 3) s
-5 547 M
-( #define SSH_FILEXFER_TYPE_SPECIAL 4) s
-5 536 M
-( #define SSH_FILEXFER_TYPE_UNKNOWN 5) s
-5 514 M
-( On a POSIX system, these values would be derived from the permission) s
-5 503 M
-( field.) s
-5 481 M
-(5.3 Size) s
-5 459 M
-( The `size' field specifies the size of the file on disk, in bytes.) s
-5 448 M
-( If it is present during file creation, it should be considered a hint) s
-5 437 M
-( as to the files eventual size.) s
-5 415 M
-( Files opened with the SSH_FXF_TEXT flag may have a size that is) s
-5 404 M
-( greater or less than the value of the size field.) s
-5 382 M
-(5.4 Owner and Group) s
-5 360 M
-( The `owner' and `group' fields are represented as UTF-8 strings; this) s
-5 349 M
-( is the form used by NFS v4. See NFS version 4 Protocol. [3] The) s
-5 338 M
-( following text is selected quotations from section 5.6.) s
-5 316 M
-( To avoid a representation that is tied to a particular underlying) s
-5 305 M
-( implementation at the client or server, the use of UTF-8 strings has) s
-5 294 M
-( been chosen. The string should be of the form user@dns_domain".) s
-5 283 M
-( This will allow for a client and server that do not use the same) s
-5 272 M
-( local representation the ability to translate to a common syntax that) s
-5 261 M
-( can be interpreted by both. In the case where there is no) s
-5 250 M
-( translation available to the client or server, the attribute value) s
-5 239 M
-( must be constructed without the "@". Therefore, the absence of the @) s
-5 228 M
-( from the owner or owner_group attribute signifies that no translation) s
-5 217 M
-( was available and the receiver of the attribute should not place any) s
-5 206 M
-( special meaning with the attribute value. Even though the attribute) s
-5 195 M
-( value can not be translated, it may still be useful. In the case of) s
-5 184 M
-( a client, the attribute string may be used for local display of) s
-5 173 M
-( ownership.) s
-5 129 M
-(Galbraith, et al. Expires April 16, 2003 [Page 10]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (10,11) 6
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 11 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH File Transfer Protocol October 2002) s
-5 690 M
-(5.5 Permissions) s
-5 668 M
-( The `permissions' field contains a bit mask of file permissions as) s
-5 657 M
-( defined by POSIX [1].) s
-5 635 M
-(5.6 Times) s
-5 613 M
-( The 'atime', 'createtime', and 'mtime' contain the access, creation,) s
-5 602 M
-( and modification times of the files, respectively. They are) s
-5 591 M
-( represented as seconds from Jan 1, 1970 in UTC.) s
-5 569 M
-(5.7 ACL) s
-5 547 M
-( The 'ACL' field contains an ACL similar to that defined in section) s
-5 536 M
-( 5.9 of NFS version 4 Protocol [3].) s
-5 514 M
-( uint32 ace-count) s
-5 492 M
-( repeated ace-count time:) s
-5 481 M
-( uint32 ace-type) s
-5 470 M
-( uint32 ace-flag) s
-5 459 M
-( uint32 ace-mask) s
-5 448 M
-( string who [UTF-8]) s
-5 426 M
-( ace-type is one of the following four values \(taken from NFS Version) s
-5 415 M
-( 4 Protocol [3]:) s
-5 393 M
-( const ACE4_ACCESS_ALLOWED_ACE_TYPE = 0x00000000;) s
-5 382 M
-( const ACE4_ACCESS_DENIED_ACE_TYPE = 0x00000001;) s
-5 371 M
-( const ACE4_SYSTEM_AUDIT_ACE_TYPE = 0x00000002;) s
-5 360 M
-( const ACE4_SYSTEM_ALARM_ACE_TYPE = 0x00000003;) s
-5 338 M
-( ace-flag is a combination of the following flag values. See NFS) s
-5 327 M
-( Version 4 Protocol [3] section 5.9.2:) s
-5 305 M
-( const ACE4_FILE_INHERIT_ACE = 0x00000001;) s
-5 294 M
-( const ACE4_DIRECTORY_INHERIT_ACE = 0x00000002;) s
-5 283 M
-( const ACE4_NO_PROPAGATE_INHERIT_ACE = 0x00000004;) s
-5 272 M
-( const ACE4_INHERIT_ONLY_ACE = 0x00000008;) s
-5 261 M
-( const ACE4_SUCCESSFUL_ACCESS_ACE_FLAG = 0x00000010;) s
-5 250 M
-( const ACE4_FAILED_ACCESS_ACE_FLAG = 0x00000020;) s
-5 239 M
-( const ACE4_IDENTIFIER_GROUP = 0x00000040;) s
-5 217 M
-( ace-mask is any combination of the following flags \(taken from NFS) s
-5 206 M
-( Version 4 Protocol [3] section 5.9.3:) s
-5 129 M
-(Galbraith, et al. Expires April 16, 2003 [Page 11]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 12 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH File Transfer Protocol October 2002) s
-5 690 M
-( const ACE4_READ_DATA = 0x00000001;) s
-5 679 M
-( const ACE4_LIST_DIRECTORY = 0x00000001;) s
-5 668 M
-( const ACE4_WRITE_DATA = 0x00000002;) s
-5 657 M
-( const ACE4_ADD_FILE = 0x00000002;) s
-5 646 M
-( const ACE4_APPEND_DATA = 0x00000004;) s
-5 635 M
-( const ACE4_ADD_SUBDIRECTORY = 0x00000004;) s
-5 624 M
-( const ACE4_READ_NAMED_ATTRS = 0x00000008;) s
-5 613 M
-( const ACE4_WRITE_NAMED_ATTRS = 0x00000010;) s
-5 602 M
-( const ACE4_EXECUTE = 0x00000020;) s
-5 591 M
-( const ACE4_DELETE_CHILD = 0x00000040;) s
-5 580 M
-( const ACE4_READ_ATTRIBUTES = 0x00000080;) s
-5 569 M
-( const ACE4_WRITE_ATTRIBUTES = 0x00000100;) s
-5 558 M
-( const ACE4_DELETE = 0x00010000;) s
-5 547 M
-( const ACE4_READ_ACL = 0x00020000;) s
-5 536 M
-( const ACE4_WRITE_ACL = 0x00040000;) s
-5 525 M
-( const ACE4_WRITE_OWNER = 0x00080000;) s
-5 514 M
-( const ACE4_SYNCHRONIZE = 0x00100000;) s
-5 492 M
-( who is a UTF-8 string of the form described in 'Owner and Group') s
-5 481 M
-( \(Section 5.4\)) s
-5 459 M
-(5.8 Extended attributes) s
-5 437 M
-( The SSH_FILEXFER_ATTR_EXTENDED flag provides a general extension) s
-5 426 M
-( mechanism for vendor-specific extensions. If the flag is specified,) s
-5 415 M
-( then the `extended_count' field is present. It specifies the number) s
-5 404 M
-( of extended_type-extended_data pairs that follow. Each of these) s
-5 393 M
-( pairs specifies an extended attribute. For each of the attributes,) s
-5 382 M
-( the extended_type field should be a string of the format) s
-5 371 M
-( "name@domain", where "domain" is a valid, registered domain name and) s
-5 360 M
-( "name" identifies the method. The IETF may later standardize certain) s
-5 349 M
-( names that deviate from this format \(e.g., that do not contain the) s
-5 338 M
-( "@" sign\). The interpretation of `extended_data' depends on the) s
-5 327 M
-( type. Implementations SHOULD ignore extended data fields that they) s
-5 316 M
-( do not understand.) s
-5 294 M
-( Additional fields can be added to the attributes by either defining) s
-5 283 M
-( additional bits to the flags field to indicate their presence, or by) s
-5 272 M
-( defining extended attributes for them. The extended attributes) s
-5 261 M
-( mechanism is recommended for most purposes; additional flags bits) s
-5 250 M
-( should only be defined by an IETF standards action that also) s
-5 239 M
-( increments the protocol version number. The use of such new fields) s
-5 228 M
-( MUST be negotiated by the version number in the protocol exchange.) s
-5 217 M
-( It is a protocol error if a packet with unsupported protocol bits is) s
-5 206 M
-( received.) s
-5 129 M
-(Galbraith, et al. Expires April 16, 2003 [Page 12]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (12,13) 7
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 13 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH File Transfer Protocol October 2002) s
-5 690 M
-(6. Requests From the Client to the Server) s
-5 668 M
-( Requests from the client to the server represent the various file) s
-5 657 M
-( system operations. Each request begins with an `id' field, which is) s
-5 646 M
-( a 32-bit identifier identifying the request \(selected by the client\).) s
-5 635 M
-( The same identifier will be returned in the response to the request.) s
-5 624 M
-( One possible implementation is a monotonically increasing request) s
-5 613 M
-( sequence number \(modulo 2^32\).) s
-5 591 M
-( Many operations in the protocol operate on open files. The) s
-5 580 M
-( SSH_FXP_OPEN request can return a file handle \(which is an opaque) s
-5 569 M
-( variable-length string\) which may be used to access the file later) s
-5 558 M
-( \(e.g. in a read operation\). The client MUST NOT send requests the) s
-5 547 M
-( server with bogus or closed handles. However, the server MUST) s
-5 536 M
-( perform adequate checks on the handle in order to avoid security) s
-5 525 M
-( risks due to fabricated handles.) s
-5 503 M
-( This design allows either stateful and stateless server) s
-5 492 M
-( implementation, as well as an implementation which caches state) s
-5 481 M
-( between requests but may also flush it. The contents of the file) s
-5 470 M
-( handle string are entirely up to the server and its design. The) s
-5 459 M
-( client should not modify or attempt to interpret the file handle) s
-5 448 M
-( strings.) s
-5 426 M
-( The file handle strings MUST NOT be longer than 256 bytes.) s
-5 404 M
-(6.1 Request Synchronization and Reordering) s
-5 382 M
-( The protocol and implementations MUST process requests relating to) s
-5 371 M
-( the same file in the order in which they are received. In other) s
-5 360 M
-( words, if an application submits multiple requests to the server, the) s
-5 349 M
-( results in the responses will be the same as if it had sent the) s
-5 338 M
-( requests one at a time and waited for the response in each case. For) s
-5 327 M
-( example, the server may process non-overlapping read/write requests) s
-5 316 M
-( to the same file in parallel, but overlapping reads and writes cannot) s
-5 305 M
-( be reordered or parallelized. However, there are no ordering) s
-5 294 M
-( restrictions on the server for processing requests from two different) s
-5 283 M
-( file transfer connections. The server may interleave and parallelize) s
-5 272 M
-( them at will.) s
-5 250 M
-( There are no restrictions on the order in which responses to) s
-5 239 M
-( outstanding requests are delivered to the client, except that the) s
-5 228 M
-( server must ensure fairness in the sense that processing of no) s
-5 217 M
-( request will be indefinitely delayed even if the client is sending) s
-5 206 M
-( other requests so that there are multiple outstanding requests all) s
-5 195 M
-( the time.) s
-5 129 M
-(Galbraith, et al. Expires April 16, 2003 [Page 13]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 14 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH File Transfer Protocol October 2002) s
-5 690 M
-(6.2 File Names) s
-5 668 M
-( This protocol represents file names as strings. File names are) s
-5 657 M
-( assumed to use the slash \('/'\) character as a directory separator.) s
-5 635 M
-( File names starting with a slash are "absolute", and are relative to) s
-5 624 M
-( the root of the file system. Names starting with any other character) s
-5 613 M
-( are relative to the user's default directory \(home directory\). Note) s
-5 602 M
-( that identifying the user is assumed to take place outside of this) s
-5 591 M
-( protocol.) s
-5 569 M
-( Servers SHOULD interpret a path name component ".." as referring to) s
-5 558 M
-( the parent directory, and "." as referring to the current directory.) s
-5 547 M
-( If the server implementation limits access to certain parts of the) s
-5 536 M
-( file system, it must be extra careful in parsing file names when) s
-5 525 M
-( enforcing such restrictions. There have been numerous reported) s
-5 514 M
-( security bugs where a ".." in a path name has allowed access outside) s
-5 503 M
-( the intended area.) s
-5 481 M
-( An empty path name is valid, and it refers to the user's default) s
-5 470 M
-( directory \(usually the user's home directory\).) s
-5 448 M
-( Otherwise, no syntax is defined for file names by this specification.) s
-5 437 M
-( Clients should not make any other assumptions; however, they can) s
-5 426 M
-( splice path name components returned by SSH_FXP_READDIR together) s
-5 415 M
-( using a slash \('/'\) as the separator, and that will work as expected.) s
-5 393 M
-( In order to comply with IETF Policy on Character Sets and Languages) s
-5 382 M
-( [2], all filenames are to be encoded in UTF-8. The shortest valid) s
-5 371 M
-( UTF-8 encoding of the UNICODE data MUST be used. The server is) s
-5 360 M
-( responsible for converting the UNICODE data to whatever canonical) s
-5 349 M
-( form it requires.) s
-5 327 M
-( For example, if the server requires that precomposed characters) s
-5 316 M
-( always be used, the server MUST NOT assume the filename as sent by) s
-5 305 M
-( the client has this attribute, but must do this normalization itself.) s
-5 283 M
-( It is understood that the lack of well-defined semantics for file) s
-5 272 M
-( names may cause interoperability problems between clients and servers) s
-5 261 M
-( using radically different operating systems. However, this approach) s
-5 250 M
-( is known to work acceptably with most systems, and alternative) s
-5 239 M
-( approaches that e.g. treat file names as sequences of structured) s
-5 228 M
-( components are quite complicated.) s
-5 206 M
-(6.3 Opening, Creating, and Closing Files) s
-5 184 M
-( Files are opened and created using the SSH_FXP_OPEN message, whose) s
-5 173 M
-( data part is as follows:) s
-5 129 M
-(Galbraith, et al. Expires April 16, 2003 [Page 14]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (14,15) 8
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 15 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH File Transfer Protocol October 2002) s
-5 690 M
-( uint32 id) s
-5 679 M
-( string filename [UTF-8]) s
-5 668 M
-( uint32 pflags) s
-5 657 M
-( ATTRS attrs) s
-5 635 M
-( The `id' field is the request identifier as for all requests.) s
-5 613 M
-( The `filename' field specifies the file name. See Section ``File) s
-5 602 M
-( Names'' for more information.) s
-5 580 M
-( The `pflags' field is a bitmask. The following bits have been) s
-5 569 M
-( defined.) s
-5 547 M
-( #define SSH_FXF_READ 0x00000001) s
-5 536 M
-( #define SSH_FXF_WRITE 0x00000002) s
-5 525 M
-( #define SSH_FXF_APPEND 0x00000004) s
-5 514 M
-( #define SSH_FXF_CREAT 0x00000008) s
-5 503 M
-( #define SSH_FXF_TRUNC 0x00000010) s
-5 492 M
-( #define SSH_FXF_EXCL 0x00000020) s
-5 481 M
-( #define SSH_FXF_TEXT 0x00000040) s
-5 459 M
-( These have the following meanings:) s
-5 437 M
-( SSH_FXF_READ) s
-5 426 M
-( Open the file for reading.) s
-5 404 M
-( SSH_FXF_WRITE) s
-5 393 M
-( Open the file for writing. If both this and SSH_FXF_READ are) s
-5 382 M
-( specified, the file is opened for both reading and writing.) s
-5 360 M
-( SSH_FXF_APPEND) s
-5 349 M
-( Force all writes to append data at the end of the file. The) s
-5 338 M
-( offset parameter to write will be ignored.) s
-5 316 M
-( SSH_FXF_CREAT) s
-5 305 M
-( If this flag is specified, then a new file will be created if one) s
-5 294 M
-( does not already exist \(if O_TRUNC is specified, the new file will) s
-5 283 M
-( be truncated to zero length if it previously exists\).) s
-5 261 M
-( SSH_FXF_TRUNC) s
-5 250 M
-( Forces an existing file with the same name to be truncated to zero) s
-5 239 M
-( length when creating a file by specifying SSH_FXF_CREAT.) s
-5 228 M
-( SSH_FXF_CREAT MUST also be specified if this flag is used.) s
-5 206 M
-( SSH_FXF_EXCL) s
-5 195 M
-( Causes the request to fail if the named file already exists.) s
-5 184 M
-( SSH_FXF_CREAT MUST also be specified if this flag is used.) s
-5 129 M
-(Galbraith, et al. Expires April 16, 2003 [Page 15]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 16 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH File Transfer Protocol October 2002) s
-5 690 M
-( SSH_FXF_TEXT) s
-5 679 M
-( Indicates that the server should treat the file as text and) s
-5 668 M
-( convert it to the canonical newline convention in use. \(See) s
-5 657 M
-( Determining Server Newline Convention. \(Section 4.3\)) s
-5 635 M
-( When a file is opened with the FXF_TEXT flag, the offset field in) s
-5 624 M
-( both the read and write function are ignored.) s
-5 602 M
-( Servers MUST correctly process multiple parallel reads and writes) s
-5 591 M
-( correctly in this mode. Naturally, it is permissible for them to) s
-5 580 M
-( do this by serializing the requests. It would not be possible for) s
-5 569 M
-( a client to reliably detect a server that does not implement) s
-5 558 M
-( parallel writes in time to prevent damage.) s
-5 536 M
-( Clients SHOULD use the SSH_FXF_APPEND flag to append data to a) s
-5 525 M
-( text file rather then using write with a calculated offset.) s
-5 503 M
-( To support seeks on text file the following SSH_FXP_EXTENDED) s
-5 492 M
-( packet is defined.) s
-5 448 M
-( string "text-seek") s
-5 437 M
-( string file-handle) s
-5 426 M
-( uint64 line-number) s
-5 404 M
-( line-number is the index of the line number to seek to, where byte) s
-5 393 M
-( 0 in the file is line number 0, and the byte directly following) s
-5 382 M
-( the first newline sequence in the file is line number 1 and so on.) s
-5 360 M
-( The response to a "text-seek" request is an SSH_FXP_STATUS) s
-5 349 M
-( message.) s
-5 327 M
-( An attempt to seek past the end-of-file should result in a) s
-5 316 M
-( SSH_FX_EOF status.) s
-5 294 M
-( Servers SHOULD support at least one "text-seek" in order to) s
-5 283 M
-( support resume. However, a client MUST be prepared to receive) s
-5 272 M
-( SSH_FX_OP_UNSUPPORTED when attempting a "text-seek" operation.) s
-5 261 M
-( The client can then try a fall-back strategy, if it has one.) s
-5 239 M
-( Clients MUST be prepared to handle SSH_FX_OP_UNSUPPORTED returned) s
-5 228 M
-( for read or write operations that are not sequential.) s
-5 206 M
-( The `attrs' field specifies the initial attributes for the file.) s
-5 195 M
-( Default values will be used for those attributes that are not) s
-5 184 M
-( specified. See Section ``File Attributes'' for more information.) s
-5 129 M
-(Galbraith, et al. Expires April 16, 2003 [Page 16]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (16,17) 9
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 17 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH File Transfer Protocol October 2002) s
-5 690 M
-( The response to this message will be either SSH_FXP_HANDLE \(if the) s
-5 679 M
-( operation is successful\) or SSH_FXP_STATUS \(if the operation fails\).) s
-5 657 M
-( A file is closed by using the SSH_FXP_CLOSE request. Its data field) s
-5 646 M
-( has the following format:) s
-5 624 M
-( uint32 id) s
-5 613 M
-( string handle) s
-5 591 M
-( where `id' is the request identifier, and `handle' is a handle) s
-5 580 M
-( previously returned in the response to SSH_FXP_OPEN or) s
-5 569 M
-( SSH_FXP_OPENDIR. The handle becomes invalid immediately after this) s
-5 558 M
-( request has been sent.) s
-5 536 M
-( The response to this request will be a SSH_FXP_STATUS message. One) s
-5 525 M
-( should note that on some server platforms even a close can fail.) s
-5 514 M
-( This can happen e.g. if the server operating system caches writes,) s
-5 503 M
-( and an error occurs while flushing cached writes during the close.) s
-5 481 M
-(6.4 Reading and Writing) s
-5 459 M
-( Once a file has been opened, it can be read using the SSH_FXP_READ) s
-5 448 M
-( message, which has the following format:) s
-5 426 M
-( uint32 id) s
-5 415 M
-( string handle) s
-5 404 M
-( uint64 offset) s
-5 393 M
-( uint32 len) s
-5 371 M
-( where `id' is the request identifier, `handle' is an open file handle) s
-5 360 M
-( returned by SSH_FXP_OPEN, `offset' is the offset \(in bytes\) relative) s
-5 349 M
-( to the beginning of the file from where to start reading, and `len') s
-5 338 M
-( is the maximum number of bytes to read.) s
-5 316 M
-( In response to this request, the server will read as many bytes as it) s
-5 305 M
-( can from the file \(up to `len'\), and return them in a SSH_FXP_DATA) s
-5 294 M
-( message. If an error occurs or EOF is encountered before reading any) s
-5 283 M
-( data, the server will respond with SSH_FXP_STATUS. For normal disk) s
-5 272 M
-( files, it is guaranteed that this will read the specified number of) s
-5 261 M
-( bytes, or up to end of file. For e.g. device files this may return) s
-5 250 M
-( fewer bytes than requested.) s
-5 228 M
-( Writing to a file is achieved using the SSH_FXP_WRITE message, which) s
-5 217 M
-( has the following format:) s
-5 129 M
-(Galbraith, et al. Expires April 16, 2003 [Page 17]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 18 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH File Transfer Protocol October 2002) s
-5 690 M
-( uint32 id) s
-5 679 M
-( string handle) s
-5 668 M
-( uint64 offset) s
-5 657 M
-( string data) s
-5 635 M
-( where `id' is a request identifier, `handle' is a file handle) s
-5 624 M
-( returned by SSH_FXP_OPEN, `offset' is the offset \(in bytes\) from the) s
-5 613 M
-( beginning of the file where to start writing, and `data' is the data) s
-5 602 M
-( to be written.) s
-5 580 M
-( The write will extend the file if writing beyond the end of the file.) s
-5 569 M
-( It is legal to write way beyond the end of the file; the semantics) s
-5 558 M
-( are to write zeroes from the end of the file to the specified offset) s
-5 547 M
-( and then the data. On most operating systems, such writes do not) s
-5 536 M
-( allocate disk space but instead leave "holes" in the file.) s
-5 514 M
-( The server responds to a write request with a SSH_FXP_STATUS message.) s
-5 492 M
-(6.5 Removing and Renaming Files) s
-5 470 M
-( Files can be removed using the SSH_FXP_REMOVE message. It has the) s
-5 459 M
-( following format:) s
-5 437 M
-( uint32 id) s
-5 426 M
-( string filename [UTF-8]) s
-5 404 M
-( where `id' is the request identifier and `filename' is the name of) s
-5 393 M
-( the file to be removed. See Section ``File Names'' for more) s
-5 382 M
-( information. This request cannot be used to remove directories.) s
-5 360 M
-( The server will respond to this request with a SSH_FXP_STATUS) s
-5 349 M
-( message.) s
-5 327 M
-( Files \(and directories\) can be renamed using the SSH_FXP_RENAME) s
-5 316 M
-( message. Its data is as follows:) s
-5 294 M
-( uint32 id) s
-5 283 M
-( string oldpath [UTF-8]) s
-5 272 M
-( string newpath [UTF-8]) s
-5 250 M
-( where `id' is the request identifier, `oldpath' is the name of an) s
-5 239 M
-( existing file or directory, and `newpath' is the new name for the) s
-5 228 M
-( file or directory. It is an error if there already exists a file) s
-5 217 M
-( with the name specified by newpath. The server may also fail rename) s
-5 206 M
-( requests in other situations, for example if `oldpath' and `newpath') s
-5 195 M
-( point to different file systems on the server.) s
-5 173 M
-( The server will respond to this request with a SSH_FXP_STATUS) s
-5 129 M
-(Galbraith, et al. Expires April 16, 2003 [Page 18]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (18,19) 10
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 19 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH File Transfer Protocol October 2002) s
-5 690 M
-( message.) s
-5 668 M
-(6.6 Creating and Deleting Directories) s
-5 646 M
-( New directories can be created using the SSH_FXP_MKDIR request. It) s
-5 635 M
-( has the following format:) s
-5 613 M
-( uint32 id) s
-5 602 M
-( string path [UTF-8]) s
-5 591 M
-( ATTRS attrs) s
-5 569 M
-( where `id' is the request identifier.) s
-5 547 M
-( `path' specifies the directory to be created. See Section ``File) s
-5 536 M
-( Names'' for more information on file names.) s
-5 514 M
-( `attrs' specifies the attributes that should be applied to it upon) s
-5 503 M
-( creation. Attributes are discussed in more detail in Section ``File) s
-5 492 M
-( Attributes''.) s
-5 470 M
-( The server will respond to this request with a SSH_FXP_STATUS) s
-5 459 M
-( message. If a file or directory with the specified path already) s
-5 448 M
-( exists, an error will be returned.) s
-5 426 M
-( Directories can be removed using the SSH_FXP_RMDIR request, which has) s
-5 415 M
-( the following format:) s
-5 393 M
-( uint32 id) s
-5 382 M
-( string path [UTF-8]) s
-5 360 M
-( where `id' is the request identifier, and `path' specifies the) s
-5 349 M
-( directory to be removed. See Section ``File Names'' for more) s
-5 338 M
-( information on file names.) s
-5 316 M
-( The server responds to this request with a SSH_FXP_STATUS message.) s
-5 305 M
-( Errors may be returned from this operation for various reasons,) s
-5 294 M
-( including, but not limited to, the path does not exist, the path does) s
-5 283 M
-( not refer to a directory object, the directory is not empty, or the) s
-5 272 M
-( user has insufficient access or permission to perform the requested) s
-5 261 M
-( operation.) s
-5 239 M
-(6.7 Scanning Directories) s
-5 217 M
-( The files in a directory can be listed using the SSH_FXP_OPENDIR and) s
-5 206 M
-( SSH_FXP_READDIR requests. Each SSH_FXP_READDIR request returns one) s
-5 195 M
-( or more file names with full file attributes for each file. The) s
-5 184 M
-( client should call SSH_FXP_READDIR repeatedly until it has found the) s
-5 173 M
-( file it is looking for or until the server responds with a) s
-5 129 M
-(Galbraith, et al. Expires April 16, 2003 [Page 19]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 20 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH File Transfer Protocol October 2002) s
-5 690 M
-( SSH_FXP_STATUS message indicating an error \(normally SSH_FX_EOF if) s
-5 679 M
-( there are no more files in the directory\). The client should then) s
-5 668 M
-( close the handle using the SSH_FXP_CLOSE request.) s
-5 646 M
-( The SSH_FXP_OPENDIR opens a directory for reading. It has the) s
-5 635 M
-( following format:) s
-5 613 M
-( uint32 id) s
-5 602 M
-( string path [UTF-8]) s
-5 580 M
-( where `id' is the request identifier and `path' is the path name of) s
-5 569 M
-( the directory to be listed \(without any trailing slash\). See Section) s
-5 558 M
-( ``File Names'' for more information on file names. This will return) s
-5 547 M
-( an error if the path does not specify a directory or if the directory) s
-5 536 M
-( is not readable. The server will respond to this request with either) s
-5 525 M
-( a SSH_FXP_HANDLE or a SSH_FXP_STATUS message.) s
-5 503 M
-( Once the directory has been successfully opened, files \(and) s
-5 492 M
-( directories\) contained in it can be listed using SSH_FXP_READDIR) s
-5 481 M
-( requests. These are of the format) s
-5 459 M
-( uint32 id) s
-5 448 M
-( string handle) s
-5 426 M
-( where `id' is the request identifier, and `handle' is a handle) s
-5 415 M
-( returned by SSH_FXP_OPENDIR. \(It is a protocol error to attempt to) s
-5 404 M
-( use an ordinary file handle returned by SSH_FXP_OPEN.\)) s
-5 382 M
-( The server responds to this request with either a SSH_FXP_NAME or a) s
-5 371 M
-( SSH_FXP_STATUS message. One or more names may be returned at a time.) s
-5 360 M
-( Full status information is returned for each name in order to speed) s
-5 349 M
-( up typical directory listings.) s
-5 327 M
-( If there are no more names available to be read, the server MUST) s
-5 316 M
-( respond with a SSH_FXP_STATUS message with error code of SSH_FX_EOF.) s
-5 294 M
-( When the client no longer wishes to read more names from the) s
-5 283 M
-( directory, it SHOULD call SSH_FXP_CLOSE for the handle. The handle) s
-5 272 M
-( should be closed regardless of whether an error has occurred or not.) s
-5 250 M
-(6.8 Retrieving File Attributes) s
-5 228 M
-( Very often, file attributes are automatically returned by) s
-5 217 M
-( SSH_FXP_READDIR. However, sometimes there is need to specifically) s
-5 206 M
-( retrieve the attributes for a named file. This can be done using the) s
-5 195 M
-( SSH_FXP_STAT, SSH_FXP_LSTAT and SSH_FXP_FSTAT requests.) s
-5 173 M
-( SSH_FXP_STAT and SSH_FXP_LSTAT only differ in that SSH_FXP_STAT) s
-5 129 M
-(Galbraith, et al. Expires April 16, 2003 [Page 20]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (20,21) 11
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 21 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH File Transfer Protocol October 2002) s
-5 690 M
-( follows symbolic links on the server, whereas SSH_FXP_LSTAT does not) s
-5 679 M
-( follow symbolic links. Both have the same format:) s
-5 657 M
-( uint32 id) s
-5 646 M
-( string path [UTF-8]) s
-5 635 M
-( uint32 flags) s
-5 613 M
-( where `id' is the request identifier, and `path' specifies the file) s
-5 602 M
-( system object for which status is to be returned. The server) s
-5 591 M
-( responds to this request with either SSH_FXP_ATTRS or SSH_FXP_STATUS.) s
-5 569 M
-( The flags field specify the attribute flags in which the client has) s
-5 558 M
-( particular interest. This is a hint to the server. For example,) s
-5 547 M
-( because retrieving owner / group and acl information can be an) s
-5 536 M
-( expensive operation under some operating systems, the server may) s
-5 525 M
-( choose not to retrieve this information unless the client expresses a) s
-5 514 M
-( specific interest in it.) s
-5 492 M
-( The client has no guarantee the server will provide all the fields) s
-5 481 M
-( that it has expressed an interest in.) s
-5 459 M
-( SSH_FXP_FSTAT differs from the others in that it returns status) s
-5 448 M
-( information for an open file \(identified by the file handle\). Its) s
-5 437 M
-( format is as follows:) s
-5 415 M
-( uint32 id) s
-5 404 M
-( string handle) s
-5 393 M
-( uint32 flags) s
-5 371 M
-( where `id' is the request identifier and `handle' is a file handle) s
-5 360 M
-( returned by SSH_FXP_OPEN. The server responds to this request with) s
-5 349 M
-( SSH_FXP_ATTRS or SSH_FXP_STATUS.) s
-5 327 M
-(6.9 Setting File Attributes) s
-5 305 M
-( File attributes may be modified using the SSH_FXP_SETSTAT and) s
-5 294 M
-( SSH_FXP_FSETSTAT requests. These requests are used for operations) s
-5 283 M
-( such as changing the ownership, permissions or access times, as well) s
-5 272 M
-( as for truncating a file.) s
-5 250 M
-( The SSH_FXP_SETSTAT request is of the following format:) s
-5 228 M
-( uint32 id) s
-5 217 M
-( string path [UTF-8]) s
-5 206 M
-( ATTRS attrs) s
-5 184 M
-( where `id' is the request identifier, `path' specifies the file) s
-5 173 M
-( system object \(e.g. file or directory\) whose attributes are to be) s
-5 129 M
-(Galbraith, et al. Expires April 16, 2003 [Page 21]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 22 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH File Transfer Protocol October 2002) s
-5 690 M
-( modified, and `attrs' specifies the modifications to be made to its) s
-5 679 M
-( attributes. Attributes are discussed in more detail in Section) s
-5 668 M
-( ``File Attributes''.) s
-5 646 M
-( An error will be returned if the specified file system object does) s
-5 635 M
-( not exist or the user does not have sufficient rights to modify the) s
-5 624 M
-( specified attributes. The server responds to this request with a) s
-5 613 M
-( SSH_FXP_STATUS message.) s
-5 591 M
-( The SSH_FXP_FSETSTAT request modifies the attributes of a file which) s
-5 580 M
-( is already open. It has the following format:) s
-5 558 M
-( uint32 id) s
-5 547 M
-( string handle) s
-5 536 M
-( ATTRS attrs) s
-5 514 M
-( where `id' is the request identifier, `handle' \(MUST be returned by) s
-5 503 M
-( SSH_FXP_OPEN\) identifies the file whose attributes are to be) s
-5 492 M
-( modified, and `attrs' specifies the modifications to be made to its) s
-5 481 M
-( attributes. Attributes are discussed in more detail in Section) s
-5 470 M
-( ``File Attributes''. The server will respond to this request with) s
-5 459 M
-( SSH_FXP_STATUS.) s
-5 437 M
-(6.10 Dealing with Symbolic links) s
-5 415 M
-( The SSH_FXP_READLINK request may be used to read the target of a) s
-5 404 M
-( symbolic link. It would have a data part as follows:) s
-5 382 M
-( uint32 id) s
-5 371 M
-( string path [UTF-8]) s
-5 349 M
-( where `id' is the request identifier and `path' specifies the path) s
-5 338 M
-( name of the symlink to be read.) s
-5 316 M
-( The server will respond with a SSH_FXP_NAME packet containing only) s
-5 305 M
-( one name and a dummy attributes value. The name in the returned) s
-5 294 M
-( packet contains the target of the link. If an error occurs, the) s
-5 283 M
-( server may respond with SSH_FXP_STATUS.) s
-5 261 M
-( The SSH_FXP_SYMLINK request will create a symbolic link on the) s
-5 250 M
-( server. It is of the following format) s
-5 228 M
-( uint32 id) s
-5 217 M
-( string linkpath [UTF-8]) s
-5 206 M
-( string targetpath [UTF-8]) s
-5 184 M
-( where `id' is the request identifier, `linkpath' specifies the path) s
-5 173 M
-( name of the symlink to be created and `targetpath' specifies the) s
-5 129 M
-(Galbraith, et al. Expires April 16, 2003 [Page 22]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (22,23) 12
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 23 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH File Transfer Protocol October 2002) s
-5 690 M
-( target of the symlink. The server shall respond with a) s
-5 679 M
-( SSH_FXP_STATUS indicating either success \(SSH_FX_OK\) or an error) s
-5 668 M
-( condition.) s
-5 646 M
-(6.11 Canonicalizing the Server-Side Path Name) s
-5 624 M
-( The SSH_FXP_REALPATH request can be used to have the server) s
-5 613 M
-( canonicalize any given path name to an absolute path. This is useful) s
-5 602 M
-( for converting path names containing ".." components or relative) s
-5 591 M
-( pathnames without a leading slash into absolute paths. The format of) s
-5 580 M
-( the request is as follows:) s
-5 558 M
-( uint32 id) s
-5 547 M
-( string path [UTF-8]) s
-5 525 M
-( where `id' is the request identifier and `path' specifies the path) s
-5 514 M
-( name to be canonicalized. The server will respond with a) s
-5 503 M
-( SSH_FXP_NAME packet containing the name in canonical form and a dummy) s
-5 492 M
-( attributes value. If an error occurs, the server may also respond) s
-5 481 M
-( with SSH_FXP_STATUS.) s
-5 459 M
-(6.11.1 Best practice for dealing with paths) s
-5 437 M
-( The client SHOULD treat the results of SSH_FXP_REALPATH as a) s
-5 426 M
-( canonical absolute path, even if the path does not appear to be) s
-5 415 M
-( absolute. A client that use REALPATH\("."\) and treats the result as) s
-5 404 M
-( absolute, even if there is no leading slash, will continue to) s
-5 393 M
-( function correctly, even when talking to a Windows NT or VMS style) s
-5 382 M
-( system, where absolute paths may not begin with a slash.) s
-5 360 M
-( For example, if the client wishes to change directory up, and the) s
-5 349 M
-( server has returned "c:/x/y/z" from REALPATH, the client SHOULD use) s
-5 338 M
-( "c:/x/y/z/..".) s
-5 316 M
-( As a second example, if the client wishes to open the file "x.txt" in) s
-5 305 M
-( the current directory, and server has returned "dka100:/x/y/z" as the) s
-5 294 M
-( canonical path of the directory, the client SHOULD open "dka100:/x/y/) s
-5 283 M
-( z/x.txt") s
-5 129 M
-(Galbraith, et al. Expires April 16, 2003 [Page 23]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 24 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH File Transfer Protocol October 2002) s
-5 690 M
-(7. Responses from the Server to the Client) s
-5 668 M
-( The server responds to the client using one of a few response) s
-5 657 M
-( packets. All requests can return a SSH_FXP_STATUS response upon) s
-5 646 M
-( failure. When the operation is successful, any of the responses may) s
-5 635 M
-( be returned \(depending on the operation\). If no data needs to be) s
-5 624 M
-( returned to the client, the SSH_FXP_STATUS response with SSH_FX_OK) s
-5 613 M
-( status is appropriate. Otherwise, the SSH_FXP_HANDLE message is used) s
-5 602 M
-( to return a file handle \(for SSH_FXP_OPEN and SSH_FXP_OPENDIR) s
-5 591 M
-( requests\), SSH_FXP_DATA is used to return data from SSH_FXP_READ,) s
-5 580 M
-( SSH_FXP_NAME is used to return one or more file names from a) s
-5 569 M
-( SSH_FXP_READDIR or SSH_FXP_REALPATH request, and SSH_FXP_ATTRS is) s
-5 558 M
-( used to return file attributes from SSH_FXP_STAT, SSH_FXP_LSTAT, and) s
-5 547 M
-( SSH_FXP_FSTAT requests.) s
-5 525 M
-( Exactly one response will be returned for each request. Each) s
-5 514 M
-( response packet contains a request identifier which can be used to) s
-5 503 M
-( match each response with the corresponding request. Note that it is) s
-5 492 M
-( legal to have several requests outstanding simultaneously, and the) s
-5 481 M
-( server is allowed to send responses to them in a different order from) s
-5 470 M
-( the order in which the requests were sent \(the result of their) s
-5 459 M
-( execution, however, is guaranteed to be as if they had been processed) s
-5 448 M
-( one at a time in the order in which the requests were sent\).) s
-5 426 M
-( Response packets are of the same general format as request packets.) s
-5 415 M
-( Each response packet begins with the request identifier.) s
-5 393 M
-( The format of the data portion of the SSH_FXP_STATUS response is as) s
-5 382 M
-( follows:) s
-5 360 M
-( uint32 id) s
-5 349 M
-( uint32 error/status code) s
-5 338 M
-( string error message \(ISO-10646 UTF-8 [RFC-2279]\)) s
-5 327 M
-( string language tag \(as defined in [RFC-1766]\)) s
-5 305 M
-( where `id' is the request identifier, and `error/status code') s
-5 294 M
-( indicates the result of the requested operation. The value SSH_FX_OK) s
-5 283 M
-( indicates success, and all other values indicate failure.) s
-5 261 M
-( Currently, the following values are defined \(other values may be) s
-5 250 M
-( defined by future versions of this protocol\):) s
-5 129 M
-(Galbraith, et al. Expires April 16, 2003 [Page 24]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (24,25) 13
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 25 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH File Transfer Protocol October 2002) s
-5 690 M
-( #define SSH_FX_OK 0) s
-5 679 M
-( #define SSH_FX_EOF 1) s
-5 668 M
-( #define SSH_FX_NO_SUCH_FILE 2) s
-5 657 M
-( #define SSH_FX_PERMISSION_DENIED 3) s
-5 646 M
-( #define SSH_FX_FAILURE 4) s
-5 635 M
-( #define SSH_FX_BAD_MESSAGE 5) s
-5 624 M
-( #define SSH_FX_NO_CONNECTION 6) s
-5 613 M
-( #define SSH_FX_CONNECTION_LOST 7) s
-5 602 M
-( #define SSH_FX_OP_UNSUPPORTED 8) s
-5 591 M
-( #define SSH_FX_INVALID_HANDLE 9) s
-5 580 M
-( #define SSH_FX_NO_SUCH_PATH 10) s
-5 569 M
-( #define SSH_FX_FILE_ALREADY_EXISTS 11) s
-5 558 M
-( #define SSH_FX_WRITE_PROTECT 12) s
-5 536 M
-( SSH_FX_OK) s
-5 525 M
-( Indicates successful completion of the operation.) s
-5 503 M
-( SSH_FX_EOF) s
-5 492 M
-( indicates end-of-file condition; for SSH_FX_READ it means that no) s
-5 481 M
-( more data is available in the file, and for SSH_FX_READDIR it) s
-5 470 M
-( indicates that no more files are contained in the directory.) s
-5 448 M
-( SSH_FX_NO_SUCH_FILE) s
-5 437 M
-( is returned when a reference is made to a file which does not) s
-5 426 M
-( exist.) s
-5 404 M
-( SSH_FX_PERMISSION_DENIED) s
-5 393 M
-( is returned when the authenticated user does not have sufficient) s
-5 382 M
-( permissions to perform the operation.) s
-5 360 M
-( SSH_FX_FAILURE) s
-5 349 M
-( is a generic catch-all error message; it should be returned if an) s
-5 338 M
-( error occurs for which there is no more specific error code) s
-5 327 M
-( defined.) s
-5 305 M
-( SSH_FX_BAD_MESSAGE) s
-5 294 M
-( may be returned if a badly formatted packet or protocol) s
-5 283 M
-( incompatibility is detected.) s
-5 261 M
-( SSH_FX_NO_CONNECTION) s
-5 250 M
-( is a pseudo-error which indicates that the client has no) s
-5 239 M
-( connection to the server \(it can only be generated locally by the) s
-5 228 M
-( client, and MUST NOT be returned by servers\).) s
-5 206 M
-( SSH_FX_CONNECTION_LOST) s
-5 195 M
-( is a pseudo-error which indicates that the connection to the) s
-5 184 M
-( server has been lost \(it can only be generated locally by the) s
-5 173 M
-( client, and MUST NOT be returned by servers\).) s
-5 129 M
-(Galbraith, et al. Expires April 16, 2003 [Page 25]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 26 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH File Transfer Protocol October 2002) s
-5 690 M
-( SSH_FX_OP_UNSUPPORTED) s
-5 679 M
-( indicates that an attempt was made to perform an operation which) s
-5 668 M
-( is not supported for the server \(it may be generated locally by) s
-5 657 M
-( the client if e.g. the version number exchange indicates that a) s
-5 646 M
-( required feature is not supported by the server, or it may be) s
-5 635 M
-( returned by the server if the server does not implement an) s
-5 624 M
-( operation\).) s
-5 602 M
-( SSH_FX_INVALID_HANDLE) s
-5 591 M
-( The handle value was invalid.) s
-5 569 M
-( SSH_FX_NO_SUCH_PATH) s
-5 558 M
-( The file path does not exist or is invalid.) s
-5 536 M
-( SSH_FX_FILE_ALREADY_EXISTS) s
-5 525 M
-( The file already exists.) s
-5 503 M
-( SSH_FX_WRITE_PROTECT) s
-5 492 M
-( The file is on read only media, or the media is write protected.) s
-5 470 M
-( The SSH_FXP_HANDLE response has the following format:) s
-5 448 M
-( uint32 id) s
-5 437 M
-( string handle) s
-5 415 M
-( where `id' is the request identifier, and `handle' is an arbitrary) s
-5 404 M
-( string that identifies an open file or directory on the server. The) s
-5 393 M
-( handle is opaque to the client; the client MUST NOT attempt to) s
-5 382 M
-( interpret or modify it in any way. The length of the handle string) s
-5 371 M
-( MUST NOT exceed 256 data bytes.) s
-5 349 M
-( The SSH_FXP_DATA response has the following format:) s
-5 327 M
-( uint32 id) s
-5 316 M
-( string data) s
-5 294 M
-( where `id' is the request identifier, and `data' is an arbitrary byte) s
-5 283 M
-( string containing the requested data. The data string may be at most) s
-5 272 M
-( the number of bytes requested in a SSH_FXP_READ request, but may also) s
-5 261 M
-( be shorter if end of file is reached or if the read is from something) s
-5 250 M
-( other than a regular file.) s
-5 228 M
-( The SSH_FXP_NAME response has the following format:) s
-5 129 M
-(Galbraith, et al. Expires April 16, 2003 [Page 26]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (26,27) 14
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 27 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH File Transfer Protocol October 2002) s
-5 690 M
-( uint32 id) s
-5 679 M
-( uint32 count) s
-5 668 M
-( repeats count times:) s
-5 657 M
-( string filename [UTF-8]) s
-5 646 M
-( ATTRS attrs) s
-5 624 M
-( where `id' is the request identifier, `count' is the number of names) s
-5 613 M
-( returned in this response, and the remaining fields repeat `count') s
-5 602 M
-( times \(so that all three fields are first included for the first) s
-5 591 M
-( file, then for the second file, etc\). In the repeated part,) s
-5 580 M
-( `filename' is a file name being returned \(for SSH_FXP_READDIR, it) s
-5 569 M
-( will be a relative name within the directory, without any path) s
-5 558 M
-( components; for SSH_FXP_REALPATH it will be an absolute path name\),) s
-5 547 M
-( and `attrs' is the attributes of the file as described in Section) s
-5 536 M
-( ``File Attributes''.) s
-5 514 M
-( The SSH_FXP_ATTRS response has the following format:) s
-5 492 M
-( uint32 id) s
-5 481 M
-( ATTRS attrs) s
-5 459 M
-( where `id' is the request identifier, and `attrs' is the returned) s
-5 448 M
-( file attributes as described in Section ``File Attributes''.) s
-5 129 M
-(Galbraith, et al. Expires April 16, 2003 [Page 27]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 28 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH File Transfer Protocol October 2002) s
-5 690 M
-(8. Vendor-Specific Extensions) s
-5 668 M
-( The SSH_FXP_EXTENDED request provides a generic extension mechanism) s
-5 657 M
-( for adding vendor-specific commands. The request has the following) s
-5 646 M
-( format:) s
-5 624 M
-( uint32 id) s
-5 613 M
-( string extended-request) s
-5 602 M
-( ... any request-specific data ...) s
-5 580 M
-( where `id' is the request identifier, and `extended-request' is a) s
-5 569 M
-( string of the format "name@domain", where domain is an internet) s
-5 558 M
-( domain name of the vendor defining the request. The rest of the) s
-5 547 M
-( request is completely vendor-specific, and servers should only) s
-5 536 M
-( attempt to interpret it if they recognize the `extended-request') s
-5 525 M
-( name.) s
-5 503 M
-( The server may respond to such requests using any of the response) s
-5 492 M
-( packets defined in Section ``Responses from the Server to the) s
-5 481 M
-( Client''. Additionally, the server may also respond with a) s
-5 470 M
-( SSH_FXP_EXTENDED_REPLY packet, as defined below. If the server does) s
-5 459 M
-( not recognize the `extended-request' name, then the server MUST) s
-5 448 M
-( respond with SSH_FXP_STATUS with error/status set to) s
-5 437 M
-( SSH_FX_OP_UNSUPPORTED.) s
-5 415 M
-( The SSH_FXP_EXTENDED_REPLY packet can be used to carry arbitrary) s
-5 404 M
-( extension-specific data from the server to the client. It is of the) s
-5 393 M
-( following format:) s
-5 371 M
-( uint32 id) s
-5 360 M
-( ... any request-specific data ...) s
-5 338 M
-( There is a range of packet types reserved for use by extensions. In) s
-5 327 M
-( order to avoid collision, extensions that turn on the use of) s
-5 316 M
-( additional packet types should determine those numbers dynamically.) s
-5 294 M
-( The suggested way of doing this is have an extension request from the) s
-5 283 M
-( client to the server that enables the extension; the extension) s
-5 272 M
-( response from the server to the client would specify the actual type) s
-5 261 M
-( values to use, in additional to any other data.) s
-5 239 M
-( Extension authors should be mindful of the limited range of packet) s
-5 228 M
-( types available \(there are only 45 values available\) and avoid) s
-5 217 M
-( requiring a new packet type where possible.) s
-5 129 M
-(Galbraith, et al. Expires April 16, 2003 [Page 28]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (28,29) 15
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 29 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH File Transfer Protocol October 2002) s
-5 690 M
-(9. Security Considerations) s
-5 668 M
-( This protocol assumes that it is run over a secure channel and that) s
-5 657 M
-( the endpoints of the channel have been authenticated. Thus, this) s
-5 646 M
-( protocol assumes that it is externally protected from network-level) s
-5 635 M
-( attacks.) s
-5 613 M
-( This protocol provides file system access to arbitrary files on the) s
-5 602 M
-( server \(only constrained by the server implementation\). It is the) s
-5 591 M
-( responsibility of the server implementation to enforce any access) s
-5 580 M
-( controls that may be required to limit the access allowed for any) s
-5 569 M
-( particular user \(the user being authenticated externally to this) s
-5 558 M
-( protocol, typically using the SSH User Authentication Protocol [8].) s
-5 536 M
-( Care must be taken in the server implementation to check the validity) s
-5 525 M
-( of received file handle strings. The server should not rely on them) s
-5 514 M
-( directly; it MUST check the validity of each handle before relying on) s
-5 503 M
-( it.) s
-5 129 M
-(Galbraith, et al. Expires April 16, 2003 [Page 29]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 30 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH File Transfer Protocol October 2002) s
-5 690 M
-(10. Changes from previous protocol versions) s
-5 668 M
-( The SSH File Transfer Protocol has changed over time, before it's) s
-5 657 M
-( standardization. The following is a description of the incompatible) s
-5 646 M
-( changes between different versions.) s
-5 624 M
-(10.1 Changes between versions 4 and 3) s
-5 602 M
-( Many of the changes between version 4 and version 3 are to the) s
-5 591 M
-( attribute structure to make it more flexible for non-unix platforms.) s
-5 569 M
-( o Make all filenames UTF-8.) s
-5 547 M
-( o Added 'newline' extension.) s
-5 525 M
-( o Made file attribute owner and group strings so they can actually) s
-5 514 M
-( be used on disparate systems.) s
-5 492 M
-( o Added createtime field, and added separate flags for atime,) s
-5 481 M
-( createtime, and mtime so they can be set separately.) s
-5 459 M
-( o Split the file type out of the permissions field and into it's own) s
-5 448 M
-( field \(which is always present.\)) s
-5 426 M
-( o Added acl attribute.) s
-5 404 M
-( o Added SSH_FXF_TEXT file open flag.) s
-5 382 M
-( o Added flags field to the get stat commands so that the client can) s
-5 371 M
-( specifically request information the server might not normally) s
-5 360 M
-( included for performance reasons.) s
-5 338 M
-( o Removed the long filename from the names structure-- it can now be) s
-5 327 M
-( built from information available in the attrs structure.) s
-5 305 M
-( o Added reserved range of packet numbers for extensions.) s
-5 283 M
-( o Added several additional error codes.) s
-5 261 M
-( o Change the way version negotiate works slightly. Previously, if) s
-5 250 M
-( the client version were higher than the server version, the server) s
-5 239 M
-( was supposed to 'echo back' the clients version. The server now) s
-5 228 M
-( sends it's own version and the lower of the two is considered to) s
-5 217 M
-( be the one in use.) s
-5 129 M
-(Galbraith, et al. Expires April 16, 2003 [Page 30]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (30,31) 16
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 31 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH File Transfer Protocol October 2002) s
-5 690 M
-(10.2 Changes between versions 3 and 2) s
-5 668 M
-( o The SSH_FXP_READLINK and SSH_FXP_SYMLINK messages were added.) s
-5 646 M
-( o The SSH_FXP_EXTENDED and SSH_FXP_EXTENDED_REPLY messages were) s
-5 635 M
-( added.) s
-5 613 M
-( o The SSH_FXP_STATUS message was changed to include fields `error) s
-5 602 M
-( message' and `language tag'.) s
-5 569 M
-(10.3 Changes between versions 2 and 1) s
-5 547 M
-( o The SSH_FXP_RENAME message was added.) s
-5 514 M
-(10.4 Changes between versions 1 and 0) s
-5 492 M
-( o Implementation changes, no actual protocol changes.) s
-5 129 M
-(Galbraith, et al. Expires April 16, 2003 [Page 31]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 32 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH File Transfer Protocol October 2002) s
-5 690 M
-(11. Trademark Issues) s
-5 668 M
-( "ssh" is a registered trademark of SSH Communications Security Corp) s
-5 657 M
-( in the United States and/or other countries.) s
-5 129 M
-(Galbraith, et al. Expires April 16, 2003 [Page 32]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (32,33) 17
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 33 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH File Transfer Protocol October 2002) s
-5 690 M
-(References) s
-5 668 M
-( [1] Dierks, T., Allen, C., Treese, W., Karlton, P., Freier, A. and) s
-5 657 M
-( P. Kocher, "The TLS Protocol Version 1.0", RFC 2246, January) s
-5 646 M
-( 1999.) s
-5 624 M
-( [2] Alvestrand, H., "IETF Policy on Character Sets and Languages",) s
-5 613 M
-( BCP 18, RFC 2277, January 1998.) s
-5 591 M
-( [3] Shepler, S., Callaghan, B., Robinson, D., Thurlow, R., Beame,) s
-5 580 M
-( C., Eisler, M. and D. Noveck, "NFS version 4 Protocol", RFC) s
-5 569 M
-( 3010, December 2000.) s
-5 547 M
-( [4] Institute of Electrical and Electronics Engineers, "Information) s
-5 536 M
-( Technology - Portable Operating System Interface \(POSIX\) - Part) s
-5 525 M
-( 1: System Application Program Interface \(API\) [C Language]",) s
-5 514 M
-( IEEE Standard 1003.2, 1996.) s
-5 492 M
-( [5] Rinne, T., Ylonen, T., Kivinen, T., Saarinen, M. and S.) s
-5 481 M
-( Lehtinen, "SSH Protocol Architecture", draft-ietf-secsh-) s
-5 470 M
-( architecture-13 \(work in progress\), September 2002.) s
-5 448 M
-( [6] Rinne, T., Ylonen, T., Kivinen, T., Saarinen, M. and S.) s
-5 437 M
-( Lehtinen, "SSH Protocol Transport Protocol", draft-ietf-secsh-) s
-5 426 M
-( transport-15 \(work in progress\), September 2002.) s
-5 404 M
-( [7] Rinne, T., Ylonen, T., Kivinen, T., Saarinen, M. and S.) s
-5 393 M
-( Lehtinen, "SSH Connection Protocol", draft-ietf-secsh-connect-16) s
-5 382 M
-( \(work in progress\), September 2002.) s
-5 360 M
-( [8] Rinne, T., Ylonen, T., Kivinen, T., Saarinen, M. and S.) s
-5 349 M
-( Lehtinen, "SSH Authentication Protocol", draft-ietf-secsh-) s
-5 338 M
-( userauth-16 \(work in progress\), September 2002.) s
-5 305 M
-(Authors' Addresses) s
-5 283 M
-( Joseph Galbraith) s
-5 272 M
-( VanDyke Software) s
-5 261 M
-( 4848 Tramway Ridge Blvd) s
-5 250 M
-( Suite 101) s
-5 239 M
-( Albuquerque, NM 87111) s
-5 228 M
-( US) s
-5 206 M
-( Phone: +1 505 332 5700) s
-5 195 M
-( EMail: [email protected]) s
-5 129 M
-(Galbraith, et al. Expires April 16, 2003 [Page 33]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 34 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH File Transfer Protocol October 2002) s
-5 690 M
-( Tatu Ylonen) s
-5 679 M
-( SSH Communications Security Corp) s
-5 668 M
-( Fredrikinkatu 42) s
-5 657 M
-( HELSINKI FIN-00100) s
-5 646 M
-( Finland) s
-5 624 M
-( EMail: [email protected]) s
-5 591 M
-( Sami Lehtinen) s
-5 580 M
-( SSH Communications Security Corp) s
-5 569 M
-( Fredrikinkatu 42) s
-5 558 M
-( HELSINKI FIN-00100) s
-5 547 M
-( Finland) s
-5 525 M
-( EMail: [email protected]) s
-5 129 M
-(Galbraith, et al. Expires April 16, 2003 [Page 34]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (34,35) 18
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 35 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH File Transfer Protocol October 2002) s
-5 690 M
-(Full Copyright Statement) s
-5 668 M
-( Copyright \(C\) The Internet Society \(2002\). All Rights Reserved.) s
-5 646 M
-( This document and translations of it may be copied and furnished to) s
-5 635 M
-( others, and derivative works that comment on or otherwise explain it) s
-5 624 M
-( or assist in its implementation may be prepared, copied, published) s
-5 613 M
-( and distributed, in whole or in part, without restriction of any) s
-5 602 M
-( kind, provided that the above copyright notice and this paragraph are) s
-5 591 M
-( included on all such copies and derivative works. However, this) s
-5 580 M
-( document itself may not be modified in any way, such as by removing) s
-5 569 M
-( the copyright notice or references to the Internet Society or other) s
-5 558 M
-( Internet organizations, except as needed for the purpose of) s
-5 547 M
-( developing Internet standards in which case the procedures for) s
-5 536 M
-( copyrights defined in the Internet Standards process must be) s
-5 525 M
-( followed, or as required to translate it into languages other than) s
-5 514 M
-( English.) s
-5 492 M
-( The limited permissions granted above are perpetual and will not be) s
-5 481 M
-( revoked by the Internet Society or its successors or assigns.) s
-5 459 M
-( This document and the information contained herein is provided on an) s
-5 448 M
-( "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING) s
-5 437 M
-( TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING) s
-5 426 M
-( BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION) s
-5 415 M
-( HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF) s
-5 404 M
-( MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.) s
-5 382 M
-(Acknowledgement) s
-5 360 M
-( Funding for the RFC Editor function is currently provided by the) s
-5 349 M
-( Internet Society.) s
-5 129 M
-(Galbraith, et al. Expires April 16, 2003 [Page 35]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 36 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-_R
-S
-PStoPSsaved restore
-%%Trailer
-%%Pages: 36
-%%DocumentNeededResources: font Courier-Bold Courier
-%%EOF
diff --git a/lib/ssh/doc/standard/draft-ietf-secsh-filexfer-03.txt b/lib/ssh/doc/standard/draft-ietf-secsh-filexfer-03.txt
deleted file mode 100644
index 83960ae976..0000000000
--- a/lib/ssh/doc/standard/draft-ietf-secsh-filexfer-03.txt
+++ /dev/null
@@ -1,1962 +0,0 @@
-
-
-
-Secure Shell Working Group J. Galbraith
-Internet-Draft VanDyke Software
-Expires: April 16, 2003 T. Ylonen
- S. Lehtinen
- SSH Communications Security Corp
- October 16, 2002
-
-
- SSH File Transfer Protocol
- draft-ietf-secsh-filexfer-03.txt
-
-Status of this Memo
-
- This document is an Internet-Draft and is in full conformance with
- all provisions of Section 10 of RFC2026.
-
- Internet-Drafts are working documents of the Internet Engineering
- Task Force (IETF), its areas, and its working groups. Note that
- other groups may also distribute working documents as Internet-
- Drafts.
-
- Internet-Drafts are draft documents valid for a maximum of six months
- and may be updated, replaced, or obsoleted by other documents at any
- time. It is inappropriate to use Internet-Drafts as reference
- material or to cite them other than as "work in progress."
-
- The list of current Internet-Drafts can be accessed at http://
- www.ietf.org/ietf/1id-abstracts.txt.
-
- The list of Internet-Draft Shadow Directories can be accessed at
- http://www.ietf.org/shadow.html.
-
- This Internet-Draft will expire on April 16, 2003.
-
-Copyright Notice
-
- Copyright (C) The Internet Society (2002). All Rights Reserved.
-
-Abstract
-
- The SSH File Transfer Protocol provides secure file transfer
- functionality over any reliable data stream. It is the standard file
- transfer protocol for use with the SSH2 protocol. This document
- describes the file transfer protocol and its interface to the SSH2
- protocol suite.
-
-
-
-
-
-
-
-Galbraith, et al. Expires April 16, 2003 [Page 1]
-
-Internet-Draft SSH File Transfer Protocol October 2002
-
-
-Table of Contents
-
- 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . 3
- 2. Use with the SSH Connection Protocol . . . . . . . . . . . 4
- 3. General Packet Format . . . . . . . . . . . . . . . . . . 5
- 4. Protocol Initialization . . . . . . . . . . . . . . . . . 7
- 4.1 Client Initialization . . . . . . . . . . . . . . . . . . 7
- 4.2 Server Initialization . . . . . . . . . . . . . . . . . . 7
- 4.3 Determining Server Newline Convention . . . . . . . . . . 8
- 5. File Attributes . . . . . . . . . . . . . . . . . . . . . 9
- 5.1 Flags . . . . . . . . . . . . . . . . . . . . . . . . . . 9
- 5.2 Type . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
- 5.3 Size . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
- 5.4 Owner and Group . . . . . . . . . . . . . . . . . . . . . 10
- 5.5 Permissions . . . . . . . . . . . . . . . . . . . . . . . 11
- 5.6 Times . . . . . . . . . . . . . . . . . . . . . . . . . . 11
- 5.7 ACL . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
- 5.8 Extended attributes . . . . . . . . . . . . . . . . . . . 12
- 6. Requests From the Client to the Server . . . . . . . . . . 13
- 6.1 Request Synchronization and Reordering . . . . . . . . . . 13
- 6.2 File Names . . . . . . . . . . . . . . . . . . . . . . . . 14
- 6.3 Opening, Creating, and Closing Files . . . . . . . . . . . 14
- 6.4 Reading and Writing . . . . . . . . . . . . . . . . . . . 17
- 6.5 Removing and Renaming Files . . . . . . . . . . . . . . . 18
- 6.6 Creating and Deleting Directories . . . . . . . . . . . . 19
- 6.7 Scanning Directories . . . . . . . . . . . . . . . . . . . 19
- 6.8 Retrieving File Attributes . . . . . . . . . . . . . . . . 20
- 6.9 Setting File Attributes . . . . . . . . . . . . . . . . . 21
- 6.10 Dealing with Symbolic links . . . . . . . . . . . . . . . 22
- 6.11 Canonicalizing the Server-Side Path Name . . . . . . . . . 23
- 6.11.1 Best practice for dealing with paths . . . . . . . . . . . 23
- 7. Responses from the Server to the Client . . . . . . . . . 24
- 8. Vendor-Specific Extensions . . . . . . . . . . . . . . . . 28
- 9. Security Considerations . . . . . . . . . . . . . . . . . 29
- 10. Changes from previous protocol versions . . . . . . . . . 30
- 10.1 Changes between versions 4 and 3 . . . . . . . . . . . . . 30
- 10.2 Changes between versions 3 and 2 . . . . . . . . . . . . . 31
- 10.3 Changes between versions 2 and 1 . . . . . . . . . . . . . 31
- 10.4 Changes between versions 1 and 0 . . . . . . . . . . . . . 31
- 11. Trademark Issues . . . . . . . . . . . . . . . . . . . . . 32
- References . . . . . . . . . . . . . . . . . . . . . . . . 33
- Authors' Addresses . . . . . . . . . . . . . . . . . . . . 33
- Full Copyright Statement . . . . . . . . . . . . . . . . . 35
-
-
-
-
-
-
-
-
-Galbraith, et al. Expires April 16, 2003 [Page 2]
-
-Internet-Draft SSH File Transfer Protocol October 2002
-
-
-1. Introduction
-
- This protocol provides secure file transfer (and more generally file
- system access) functionality over a reliable data stream, such as a
- channel in the SSH2 protocol [5].
-
- This protocol is designed so that it could be used to implement a
- secure remote file system service, as well as a secure file transfer
- service.
-
- This protocol assumes that it runs over a secure channel, and that
- the server has already authenticated the user at the client end, and
- that the identity of the client user is externally available to the
- server implementation.
-
- In general, this protocol follows a simple request-response model.
- Each request and response contains a sequence number and multiple
- requests may be pending simultaneously. There are a relatively large
- number of different request messages, but a small number of possible
- response messages. Each request has one or more response messages
- that may be returned in result (e.g., a read either returns data or
- reports error status).
-
- The packet format descriptions in this specification follow the
- notation presented in the secsh architecture draft. [5]
-
- Even though this protocol is described in the context of the SSH2
- protocol, this protocol is general and independent of the rest of the
- SSH2 protocol suite. It could be used in a number of different
- applications, such as secure file transfer over TLS RFC 2246 [1] and
- transfer of management information in VPN applications.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Galbraith, et al. Expires April 16, 2003 [Page 3]
-
-Internet-Draft SSH File Transfer Protocol October 2002
-
-
-2. Use with the SSH Connection Protocol
-
- When used with the SSH2 Protocol suite, this protocol is intended to
- be used from the SSH Connection Protocol [7] as a subsystem, as
- described in section ``Starting a Shell or a Command''. The
- subsystem name used with this protocol is "sftp".
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Galbraith, et al. Expires April 16, 2003 [Page 4]
-
-Internet-Draft SSH File Transfer Protocol October 2002
-
-
-3. General Packet Format
-
- All packets transmitted over the secure connection are of the
- following format:
-
- uint32 length
- byte type
- byte[length - 1] data payload
-
- That is, they are just data preceded by 32-bit length and 8-bit type
- fields. The `length' is the length of the data area, and does not
- include the `length' field itself. The format and interpretation of
- the data area depends on the packet type.
-
- All packet descriptions below only specify the packet type and the
- data that goes into the data field. Thus, they should be prefixed by
- the `length' and `type' fields.
-
- The maximum size of a packet is in practice determined by the client
- (the maximum size of read or write requests that it sends, plus a few
- bytes of packet overhead). All servers SHOULD support packets of at
- least 34000 bytes (where the packet size refers to the full length,
- including the header above). This should allow for reads and writes
- of at most 32768 bytes.
-
- There is no limit on the number of outstanding (non-acknowledged)
- requests that the client may send to the server. In practice this is
- limited by the buffering available on the data stream and the queuing
- performed by the server. If the server's queues are full, it should
- not read any more data from the stream, and flow control will prevent
- the client from sending more requests. Note, however, that while
- there is no restriction on the protocol level, the client's API may
- provide a limit in order to prevent infinite queuing of outgoing
- requests at the client.
-
- The following values are defined for packet types.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Galbraith, et al. Expires April 16, 2003 [Page 5]
-
-Internet-Draft SSH File Transfer Protocol October 2002
-
-
- #define SSH_FXP_INIT 1
- #define SSH_FXP_VERSION 2
- #define SSH_FXP_OPEN 3
- #define SSH_FXP_CLOSE 4
- #define SSH_FXP_READ 5
- #define SSH_FXP_WRITE 6
- #define SSH_FXP_LSTAT 7
- #define SSH_FXP_FSTAT 8
- #define SSH_FXP_SETSTAT 9
- #define SSH_FXP_FSETSTAT 10
- #define SSH_FXP_OPENDIR 11
- #define SSH_FXP_READDIR 12
- #define SSH_FXP_REMOVE 13
- #define SSH_FXP_MKDIR 14
- #define SSH_FXP_RMDIR 15
- #define SSH_FXP_REALPATH 16
- #define SSH_FXP_STAT 17
- #define SSH_FXP_RENAME 18
- #define SSH_FXP_READLINK 19
- #define SSH_FXP_SYMLINK 20
-
- #define SSH_FXP_STATUS 101
- #define SSH_FXP_HANDLE 102
- #define SSH_FXP_DATA 103
- #define SSH_FXP_NAME 104
- #define SSH_FXP_ATTRS 105
-
- #define SSH_FXP_EXTENDED 200
- #define SSH_FXP_EXTENDED_REPLY 201
-
- RESERVED_FOR_EXTENSIONS 210-255
-
- Additional packet types should only be defined if the protocol
- version number (see Section ``Protocol Initialization'') is
- incremented, and their use MUST be negotiated using the version
- number. However, the SSH_FXP_EXTENDED and SSH_FXP_EXTENDED_REPLY
- packets can be used to implement vendor-specific extensions. See
- Section ``Vendor-Specific-Extensions'' for more details.
-
-
-
-
-
-
-
-
-
-
-
-
-
-Galbraith, et al. Expires April 16, 2003 [Page 6]
-
-Internet-Draft SSH File Transfer Protocol October 2002
-
-
-4. Protocol Initialization
-
- When the file transfer protocol starts, the client first sends a
- SSH_FXP_INIT (including its version number) packet to the server.
- The server responds with a SSH_FXP_VERSION packet, supplying the
- lowest of its own and the client's version number. Both parties
- should from then on adhere to particular version of the protocol.
-
- The version number of the protocol specified in this document is 4.
- The version number should be incremented for each incompatible
- revision of this protocol.
-
-4.1 Client Initialization
-
- The SSH_FXP_INIT packet (from client to server) has the following
- data:
-
- uint32 version
-
- Version 3 of this protocol allowed clients to include extensions in
- the SSH_FXP_INIT packet; however, this can cause interoperability
- problems with version 1 and version 2 servers because the client must
- send this packet before knowing the servers version.
-
- In this version of the protocol, clients MUST use the
- SSH_FXP_EXTENDED packet to send extensions to the server after
- version exchange has completed. Clients MUST NOT include extensions
- in the version packet. This will prevent interoperability problems
- with older servers
-
-4.2 Server Initialization
-
- The SSH_FXP_VERSION packet (from server to client) has the following
- data:
-
- uint32 version
- <extension data>
-
- 'version' is the lower of the protocol version supported by the
- server and the version number received from the client.
-
- The extension data may be empty, or may be a sequence of
-
- string extension_name
- string extension_data
-
- pairs (both strings MUST always be present if one is, but the
- `extension_data' string may be of zero length). If present, these
-
-
-
-Galbraith, et al. Expires April 16, 2003 [Page 7]
-
-Internet-Draft SSH File Transfer Protocol October 2002
-
-
- strings indicate extensions to the baseline protocol. The
- `extension_name' field(s) identify the name of the extension. The
- name should be of the form "name@domain", where the domain is the DNS
- domain name of the organization defining the extension. Additional
- names that are not of this format may be defined later by the IETF.
- Implementations MUST silently ignore any extensions whose name they
- do not recognize.
-
-4.3 Determining Server Newline Convention
-
- In order to correctly process text files in a cross platform
- compatible way, the newline convention must be converted from that of
- the server to that of the client, or, during an upload, from that of
- the client to that of the server.
-
- Versions 3 and prior of this protocol made no provisions for
- processing text files. Many clients implemented some sort of
- conversion algorithm, but without either a 'canonical' on the wire
- format or knowledge of the servers newline convention, correct
- conversion was not always possible.
-
- Starting with Version 4, the SSH_FXF_TEXT file open flag (Section
- 6.3) makes it possible to request that the server translate a file to
- a 'canonical' on the wire format. This format uses \r\n as the line
- separator.
-
- Servers for systems using multiple newline characters (for example,
- Mac OS X or VMS) or systems using counted records, MUST translate to
- the canonical form.
-
- However, to ease the burden of implementation on servers that use a
- single, simple separator sequence, the following extension allows the
- canonical format to be changed.
-
- string "newline"
- string new-canonical-separator (usually "\r" or "\n" or "\r\n")
-
- All clients MUST support this extension.
-
- When processing text files, clients SHOULD NOT translate any
- character or sequence that is not an exact match of the servers
- newline separator.
-
- In particular, if the newline sequence being used is the canonical
- "\r\n" sequence, a lone \r or a lone \n SHOULD be written through
- without change.
-
-
-
-
-
-Galbraith, et al. Expires April 16, 2003 [Page 8]
-
-Internet-Draft SSH File Transfer Protocol October 2002
-
-
-5. File Attributes
-
- A new compound data type is defined for encoding file attributes.
- The same encoding is used both when returning file attributes from
- the server and when sending file attributes to the server. When
- sending it to the server, the flags field specifies which attributes
- are included, and the server will use default values for the
- remaining attributes (or will not modify the values of remaining
- attributes). When receiving attributes from the server, the flags
- specify which attributes are included in the returned data. The
- server normally returns all attributes it knows about.
-
- uint32 flags
- byte type always present
- uint64 size present only if flag SSH_FILEXFER_ATTR_SIZE
- string owner present only if flag SSH_FILEXFER_ATTR_OWNERGROUP
- string group present only if flag SSH_FILEXFER_ATTR_OWNERGROUP
- uint32 permissions present only if flag SSH_FILEXFER_ATTR_PERMISSIONS
- uint32 atime present only if flag SSH_FILEXFER_ATTR_ACCESSTIME
- uint32 createtime present only if flag SSH_FILEXFER_ATTR_CREATETIME
- uint32 mtime present only if flag SSH_FILEXFER_ATTR_MODIFYTIME
- string acl present only if flag SSH_FILEXFER_ATTR_ACL
- uint32 extended_count present only if flag SSH_FILEXFER_ATTR_EXTENDED
- string extended_type
- string extended_data
- ... more extended data (extended_type - extended_data pairs),
- so that number of pairs equals extended_count
-
-
-5.1 Flags
-
- The `flags' specify which of the fields are present. Those fields
- for which the corresponding flag is not set are not present (not
- included in the packet). New flags can only be added by incrementing
- the protocol version number (or by using the extension mechanism
- described below).
-
- The flags bits are defined to have the following values:
-
- #define SSH_FILEXFER_ATTR_SIZE 0x00000001
- #define SSH_FILEXFER_ATTR_PERMISSIONS 0x00000004
- #define SSH_FILEXFER_ATTR_ACCESSTIME 0x00000008
- #define SSH_FILEXFER_ATTR_CREATETIME 0x00000010
- #define SSH_FILEXFER_ATTR_MODIFYTIME 0x00000020
- #define SSH_FILEXFER_ATTR_ACL 0x00000040
- #define SSH_FILEXFER_ATTR_OWNERGROUP 0x00000080
- #define SSH_FILEXFER_ATTR_EXTENDED 0x80000000
-
-
-
-
-Galbraith, et al. Expires April 16, 2003 [Page 9]
-
-Internet-Draft SSH File Transfer Protocol October 2002
-
-
- In previous versions of this protocol flags value 0x00000002 was
- SSH_FILEXFER_ATTR_UIDGID. This value is now unused, and OWNERGROUP
- was given a new value in order to ease implementation burden.
- 0x00000002 MUST NOT appear in the mask. Some future version of this
- protocol may reuse flag 0x00000002.
-
-5.2 Type
-
- The type field is always present. The following types are defined:
-
- #define SSH_FILEXFER_TYPE_REGULAR 1
- #define SSH_FILEXFER_TYPE_DIRECTORY 2
- #define SSH_FILEXFER_TYPE_SYMLINK 3
- #define SSH_FILEXFER_TYPE_SPECIAL 4
- #define SSH_FILEXFER_TYPE_UNKNOWN 5
-
- On a POSIX system, these values would be derived from the permission
- field.
-
-5.3 Size
-
- The `size' field specifies the size of the file on disk, in bytes.
- If it is present during file creation, it should be considered a hint
- as to the files eventual size.
-
- Files opened with the SSH_FXF_TEXT flag may have a size that is
- greater or less than the value of the size field.
-
-5.4 Owner and Group
-
- The `owner' and `group' fields are represented as UTF-8 strings; this
- is the form used by NFS v4. See NFS version 4 Protocol. [3] The
- following text is selected quotations from section 5.6.
-
- To avoid a representation that is tied to a particular underlying
- implementation at the client or server, the use of UTF-8 strings has
- been chosen. The string should be of the form user@dns_domain".
- This will allow for a client and server that do not use the same
- local representation the ability to translate to a common syntax that
- can be interpreted by both. In the case where there is no
- translation available to the client or server, the attribute value
- must be constructed without the "@". Therefore, the absence of the @
- from the owner or owner_group attribute signifies that no translation
- was available and the receiver of the attribute should not place any
- special meaning with the attribute value. Even though the attribute
- value can not be translated, it may still be useful. In the case of
- a client, the attribute string may be used for local display of
- ownership.
-
-
-
-Galbraith, et al. Expires April 16, 2003 [Page 10]
-
-Internet-Draft SSH File Transfer Protocol October 2002
-
-
-5.5 Permissions
-
- The `permissions' field contains a bit mask of file permissions as
- defined by POSIX [1].
-
-5.6 Times
-
- The 'atime', 'createtime', and 'mtime' contain the access, creation,
- and modification times of the files, respectively. They are
- represented as seconds from Jan 1, 1970 in UTC.
-
-5.7 ACL
-
- The 'ACL' field contains an ACL similar to that defined in section
- 5.9 of NFS version 4 Protocol [3].
-
- uint32 ace-count
-
- repeated ace-count time:
- uint32 ace-type
- uint32 ace-flag
- uint32 ace-mask
- string who [UTF-8]
-
- ace-type is one of the following four values (taken from NFS Version
- 4 Protocol [3]:
-
- const ACE4_ACCESS_ALLOWED_ACE_TYPE = 0x00000000;
- const ACE4_ACCESS_DENIED_ACE_TYPE = 0x00000001;
- const ACE4_SYSTEM_AUDIT_ACE_TYPE = 0x00000002;
- const ACE4_SYSTEM_ALARM_ACE_TYPE = 0x00000003;
-
- ace-flag is a combination of the following flag values. See NFS
- Version 4 Protocol [3] section 5.9.2:
-
- const ACE4_FILE_INHERIT_ACE = 0x00000001;
- const ACE4_DIRECTORY_INHERIT_ACE = 0x00000002;
- const ACE4_NO_PROPAGATE_INHERIT_ACE = 0x00000004;
- const ACE4_INHERIT_ONLY_ACE = 0x00000008;
- const ACE4_SUCCESSFUL_ACCESS_ACE_FLAG = 0x00000010;
- const ACE4_FAILED_ACCESS_ACE_FLAG = 0x00000020;
- const ACE4_IDENTIFIER_GROUP = 0x00000040;
-
- ace-mask is any combination of the following flags (taken from NFS
- Version 4 Protocol [3] section 5.9.3:
-
-
-
-
-
-
-Galbraith, et al. Expires April 16, 2003 [Page 11]
-
-Internet-Draft SSH File Transfer Protocol October 2002
-
-
- const ACE4_READ_DATA = 0x00000001;
- const ACE4_LIST_DIRECTORY = 0x00000001;
- const ACE4_WRITE_DATA = 0x00000002;
- const ACE4_ADD_FILE = 0x00000002;
- const ACE4_APPEND_DATA = 0x00000004;
- const ACE4_ADD_SUBDIRECTORY = 0x00000004;
- const ACE4_READ_NAMED_ATTRS = 0x00000008;
- const ACE4_WRITE_NAMED_ATTRS = 0x00000010;
- const ACE4_EXECUTE = 0x00000020;
- const ACE4_DELETE_CHILD = 0x00000040;
- const ACE4_READ_ATTRIBUTES = 0x00000080;
- const ACE4_WRITE_ATTRIBUTES = 0x00000100;
- const ACE4_DELETE = 0x00010000;
- const ACE4_READ_ACL = 0x00020000;
- const ACE4_WRITE_ACL = 0x00040000;
- const ACE4_WRITE_OWNER = 0x00080000;
- const ACE4_SYNCHRONIZE = 0x00100000;
-
- who is a UTF-8 string of the form described in 'Owner and Group'
- (Section 5.4)
-
-5.8 Extended attributes
-
- The SSH_FILEXFER_ATTR_EXTENDED flag provides a general extension
- mechanism for vendor-specific extensions. If the flag is specified,
- then the `extended_count' field is present. It specifies the number
- of extended_type-extended_data pairs that follow. Each of these
- pairs specifies an extended attribute. For each of the attributes,
- the extended_type field should be a string of the format
- "name@domain", where "domain" is a valid, registered domain name and
- "name" identifies the method. The IETF may later standardize certain
- names that deviate from this format (e.g., that do not contain the
- "@" sign). The interpretation of `extended_data' depends on the
- type. Implementations SHOULD ignore extended data fields that they
- do not understand.
-
- Additional fields can be added to the attributes by either defining
- additional bits to the flags field to indicate their presence, or by
- defining extended attributes for them. The extended attributes
- mechanism is recommended for most purposes; additional flags bits
- should only be defined by an IETF standards action that also
- increments the protocol version number. The use of such new fields
- MUST be negotiated by the version number in the protocol exchange.
- It is a protocol error if a packet with unsupported protocol bits is
- received.
-
-
-
-
-
-
-Galbraith, et al. Expires April 16, 2003 [Page 12]
-
-Internet-Draft SSH File Transfer Protocol October 2002
-
-
-6. Requests From the Client to the Server
-
- Requests from the client to the server represent the various file
- system operations. Each request begins with an `id' field, which is
- a 32-bit identifier identifying the request (selected by the client).
- The same identifier will be returned in the response to the request.
- One possible implementation is a monotonically increasing request
- sequence number (modulo 2^32).
-
- Many operations in the protocol operate on open files. The
- SSH_FXP_OPEN request can return a file handle (which is an opaque
- variable-length string) which may be used to access the file later
- (e.g. in a read operation). The client MUST NOT send requests the
- server with bogus or closed handles. However, the server MUST
- perform adequate checks on the handle in order to avoid security
- risks due to fabricated handles.
-
- This design allows either stateful and stateless server
- implementation, as well as an implementation which caches state
- between requests but may also flush it. The contents of the file
- handle string are entirely up to the server and its design. The
- client should not modify or attempt to interpret the file handle
- strings.
-
- The file handle strings MUST NOT be longer than 256 bytes.
-
-6.1 Request Synchronization and Reordering
-
- The protocol and implementations MUST process requests relating to
- the same file in the order in which they are received. In other
- words, if an application submits multiple requests to the server, the
- results in the responses will be the same as if it had sent the
- requests one at a time and waited for the response in each case. For
- example, the server may process non-overlapping read/write requests
- to the same file in parallel, but overlapping reads and writes cannot
- be reordered or parallelized. However, there are no ordering
- restrictions on the server for processing requests from two different
- file transfer connections. The server may interleave and parallelize
- them at will.
-
- There are no restrictions on the order in which responses to
- outstanding requests are delivered to the client, except that the
- server must ensure fairness in the sense that processing of no
- request will be indefinitely delayed even if the client is sending
- other requests so that there are multiple outstanding requests all
- the time.
-
-
-
-
-
-Galbraith, et al. Expires April 16, 2003 [Page 13]
-
-Internet-Draft SSH File Transfer Protocol October 2002
-
-
-6.2 File Names
-
- This protocol represents file names as strings. File names are
- assumed to use the slash ('/') character as a directory separator.
-
- File names starting with a slash are "absolute", and are relative to
- the root of the file system. Names starting with any other character
- are relative to the user's default directory (home directory). Note
- that identifying the user is assumed to take place outside of this
- protocol.
-
- Servers SHOULD interpret a path name component ".." as referring to
- the parent directory, and "." as referring to the current directory.
- If the server implementation limits access to certain parts of the
- file system, it must be extra careful in parsing file names when
- enforcing such restrictions. There have been numerous reported
- security bugs where a ".." in a path name has allowed access outside
- the intended area.
-
- An empty path name is valid, and it refers to the user's default
- directory (usually the user's home directory).
-
- Otherwise, no syntax is defined for file names by this specification.
- Clients should not make any other assumptions; however, they can
- splice path name components returned by SSH_FXP_READDIR together
- using a slash ('/') as the separator, and that will work as expected.
-
- In order to comply with IETF Policy on Character Sets and Languages
- [2], all filenames are to be encoded in UTF-8. The shortest valid
- UTF-8 encoding of the UNICODE data MUST be used. The server is
- responsible for converting the UNICODE data to whatever canonical
- form it requires.
-
- For example, if the server requires that precomposed characters
- always be used, the server MUST NOT assume the filename as sent by
- the client has this attribute, but must do this normalization itself.
-
- It is understood that the lack of well-defined semantics for file
- names may cause interoperability problems between clients and servers
- using radically different operating systems. However, this approach
- is known to work acceptably with most systems, and alternative
- approaches that e.g. treat file names as sequences of structured
- components are quite complicated.
-
-6.3 Opening, Creating, and Closing Files
-
- Files are opened and created using the SSH_FXP_OPEN message, whose
- data part is as follows:
-
-
-
-Galbraith, et al. Expires April 16, 2003 [Page 14]
-
-Internet-Draft SSH File Transfer Protocol October 2002
-
-
- uint32 id
- string filename [UTF-8]
- uint32 pflags
- ATTRS attrs
-
- The `id' field is the request identifier as for all requests.
-
- The `filename' field specifies the file name. See Section ``File
- Names'' for more information.
-
- The `pflags' field is a bitmask. The following bits have been
- defined.
-
- #define SSH_FXF_READ 0x00000001
- #define SSH_FXF_WRITE 0x00000002
- #define SSH_FXF_APPEND 0x00000004
- #define SSH_FXF_CREAT 0x00000008
- #define SSH_FXF_TRUNC 0x00000010
- #define SSH_FXF_EXCL 0x00000020
- #define SSH_FXF_TEXT 0x00000040
-
- These have the following meanings:
-
- SSH_FXF_READ
- Open the file for reading.
-
- SSH_FXF_WRITE
- Open the file for writing. If both this and SSH_FXF_READ are
- specified, the file is opened for both reading and writing.
-
- SSH_FXF_APPEND
- Force all writes to append data at the end of the file. The
- offset parameter to write will be ignored.
-
- SSH_FXF_CREAT
- If this flag is specified, then a new file will be created if one
- does not already exist (if O_TRUNC is specified, the new file will
- be truncated to zero length if it previously exists).
-
- SSH_FXF_TRUNC
- Forces an existing file with the same name to be truncated to zero
- length when creating a file by specifying SSH_FXF_CREAT.
- SSH_FXF_CREAT MUST also be specified if this flag is used.
-
- SSH_FXF_EXCL
- Causes the request to fail if the named file already exists.
- SSH_FXF_CREAT MUST also be specified if this flag is used.
-
-
-
-
-Galbraith, et al. Expires April 16, 2003 [Page 15]
-
-Internet-Draft SSH File Transfer Protocol October 2002
-
-
- SSH_FXF_TEXT
- Indicates that the server should treat the file as text and
- convert it to the canonical newline convention in use. (See
- Determining Server Newline Convention. (Section 4.3)
-
- When a file is opened with the FXF_TEXT flag, the offset field in
- both the read and write function are ignored.
-
- Servers MUST correctly process multiple parallel reads and writes
- correctly in this mode. Naturally, it is permissible for them to
- do this by serializing the requests. It would not be possible for
- a client to reliably detect a server that does not implement
- parallel writes in time to prevent damage.
-
- Clients SHOULD use the SSH_FXF_APPEND flag to append data to a
- text file rather then using write with a calculated offset.
-
- To support seeks on text file the following SSH_FXP_EXTENDED
- packet is defined.
-
-
-
- string "text-seek"
- string file-handle
- uint64 line-number
-
- line-number is the index of the line number to seek to, where byte
- 0 in the file is line number 0, and the byte directly following
- the first newline sequence in the file is line number 1 and so on.
-
- The response to a "text-seek" request is an SSH_FXP_STATUS
- message.
-
- An attempt to seek past the end-of-file should result in a
- SSH_FX_EOF status.
-
- Servers SHOULD support at least one "text-seek" in order to
- support resume. However, a client MUST be prepared to receive
- SSH_FX_OP_UNSUPPORTED when attempting a "text-seek" operation.
- The client can then try a fall-back strategy, if it has one.
-
- Clients MUST be prepared to handle SSH_FX_OP_UNSUPPORTED returned
- for read or write operations that are not sequential.
-
- The `attrs' field specifies the initial attributes for the file.
- Default values will be used for those attributes that are not
- specified. See Section ``File Attributes'' for more information.
-
-
-
-
-Galbraith, et al. Expires April 16, 2003 [Page 16]
-
-Internet-Draft SSH File Transfer Protocol October 2002
-
-
- The response to this message will be either SSH_FXP_HANDLE (if the
- operation is successful) or SSH_FXP_STATUS (if the operation fails).
-
- A file is closed by using the SSH_FXP_CLOSE request. Its data field
- has the following format:
-
- uint32 id
- string handle
-
- where `id' is the request identifier, and `handle' is a handle
- previously returned in the response to SSH_FXP_OPEN or
- SSH_FXP_OPENDIR. The handle becomes invalid immediately after this
- request has been sent.
-
- The response to this request will be a SSH_FXP_STATUS message. One
- should note that on some server platforms even a close can fail.
- This can happen e.g. if the server operating system caches writes,
- and an error occurs while flushing cached writes during the close.
-
-6.4 Reading and Writing
-
- Once a file has been opened, it can be read using the SSH_FXP_READ
- message, which has the following format:
-
- uint32 id
- string handle
- uint64 offset
- uint32 len
-
- where `id' is the request identifier, `handle' is an open file handle
- returned by SSH_FXP_OPEN, `offset' is the offset (in bytes) relative
- to the beginning of the file from where to start reading, and `len'
- is the maximum number of bytes to read.
-
- In response to this request, the server will read as many bytes as it
- can from the file (up to `len'), and return them in a SSH_FXP_DATA
- message. If an error occurs or EOF is encountered before reading any
- data, the server will respond with SSH_FXP_STATUS. For normal disk
- files, it is guaranteed that this will read the specified number of
- bytes, or up to end of file. For e.g. device files this may return
- fewer bytes than requested.
-
- Writing to a file is achieved using the SSH_FXP_WRITE message, which
- has the following format:
-
-
-
-
-
-
-
-Galbraith, et al. Expires April 16, 2003 [Page 17]
-
-Internet-Draft SSH File Transfer Protocol October 2002
-
-
- uint32 id
- string handle
- uint64 offset
- string data
-
- where `id' is a request identifier, `handle' is a file handle
- returned by SSH_FXP_OPEN, `offset' is the offset (in bytes) from the
- beginning of the file where to start writing, and `data' is the data
- to be written.
-
- The write will extend the file if writing beyond the end of the file.
- It is legal to write way beyond the end of the file; the semantics
- are to write zeroes from the end of the file to the specified offset
- and then the data. On most operating systems, such writes do not
- allocate disk space but instead leave "holes" in the file.
-
- The server responds to a write request with a SSH_FXP_STATUS message.
-
-6.5 Removing and Renaming Files
-
- Files can be removed using the SSH_FXP_REMOVE message. It has the
- following format:
-
- uint32 id
- string filename [UTF-8]
-
- where `id' is the request identifier and `filename' is the name of
- the file to be removed. See Section ``File Names'' for more
- information. This request cannot be used to remove directories.
-
- The server will respond to this request with a SSH_FXP_STATUS
- message.
-
- Files (and directories) can be renamed using the SSH_FXP_RENAME
- message. Its data is as follows:
-
- uint32 id
- string oldpath [UTF-8]
- string newpath [UTF-8]
-
- where `id' is the request identifier, `oldpath' is the name of an
- existing file or directory, and `newpath' is the new name for the
- file or directory. It is an error if there already exists a file
- with the name specified by newpath. The server may also fail rename
- requests in other situations, for example if `oldpath' and `newpath'
- point to different file systems on the server.
-
- The server will respond to this request with a SSH_FXP_STATUS
-
-
-
-Galbraith, et al. Expires April 16, 2003 [Page 18]
-
-Internet-Draft SSH File Transfer Protocol October 2002
-
-
- message.
-
-6.6 Creating and Deleting Directories
-
- New directories can be created using the SSH_FXP_MKDIR request. It
- has the following format:
-
- uint32 id
- string path [UTF-8]
- ATTRS attrs
-
- where `id' is the request identifier.
-
- `path' specifies the directory to be created. See Section ``File
- Names'' for more information on file names.
-
- `attrs' specifies the attributes that should be applied to it upon
- creation. Attributes are discussed in more detail in Section ``File
- Attributes''.
-
- The server will respond to this request with a SSH_FXP_STATUS
- message. If a file or directory with the specified path already
- exists, an error will be returned.
-
- Directories can be removed using the SSH_FXP_RMDIR request, which has
- the following format:
-
- uint32 id
- string path [UTF-8]
-
- where `id' is the request identifier, and `path' specifies the
- directory to be removed. See Section ``File Names'' for more
- information on file names.
-
- The server responds to this request with a SSH_FXP_STATUS message.
- Errors may be returned from this operation for various reasons,
- including, but not limited to, the path does not exist, the path does
- not refer to a directory object, the directory is not empty, or the
- user has insufficient access or permission to perform the requested
- operation.
-
-6.7 Scanning Directories
-
- The files in a directory can be listed using the SSH_FXP_OPENDIR and
- SSH_FXP_READDIR requests. Each SSH_FXP_READDIR request returns one
- or more file names with full file attributes for each file. The
- client should call SSH_FXP_READDIR repeatedly until it has found the
- file it is looking for or until the server responds with a
-
-
-
-Galbraith, et al. Expires April 16, 2003 [Page 19]
-
-Internet-Draft SSH File Transfer Protocol October 2002
-
-
- SSH_FXP_STATUS message indicating an error (normally SSH_FX_EOF if
- there are no more files in the directory). The client should then
- close the handle using the SSH_FXP_CLOSE request.
-
- The SSH_FXP_OPENDIR opens a directory for reading. It has the
- following format:
-
- uint32 id
- string path [UTF-8]
-
- where `id' is the request identifier and `path' is the path name of
- the directory to be listed (without any trailing slash). See Section
- ``File Names'' for more information on file names. This will return
- an error if the path does not specify a directory or if the directory
- is not readable. The server will respond to this request with either
- a SSH_FXP_HANDLE or a SSH_FXP_STATUS message.
-
- Once the directory has been successfully opened, files (and
- directories) contained in it can be listed using SSH_FXP_READDIR
- requests. These are of the format
-
- uint32 id
- string handle
-
- where `id' is the request identifier, and `handle' is a handle
- returned by SSH_FXP_OPENDIR. (It is a protocol error to attempt to
- use an ordinary file handle returned by SSH_FXP_OPEN.)
-
- The server responds to this request with either a SSH_FXP_NAME or a
- SSH_FXP_STATUS message. One or more names may be returned at a time.
- Full status information is returned for each name in order to speed
- up typical directory listings.
-
- If there are no more names available to be read, the server MUST
- respond with a SSH_FXP_STATUS message with error code of SSH_FX_EOF.
-
- When the client no longer wishes to read more names from the
- directory, it SHOULD call SSH_FXP_CLOSE for the handle. The handle
- should be closed regardless of whether an error has occurred or not.
-
-6.8 Retrieving File Attributes
-
- Very often, file attributes are automatically returned by
- SSH_FXP_READDIR. However, sometimes there is need to specifically
- retrieve the attributes for a named file. This can be done using the
- SSH_FXP_STAT, SSH_FXP_LSTAT and SSH_FXP_FSTAT requests.
-
- SSH_FXP_STAT and SSH_FXP_LSTAT only differ in that SSH_FXP_STAT
-
-
-
-Galbraith, et al. Expires April 16, 2003 [Page 20]
-
-Internet-Draft SSH File Transfer Protocol October 2002
-
-
- follows symbolic links on the server, whereas SSH_FXP_LSTAT does not
- follow symbolic links. Both have the same format:
-
- uint32 id
- string path [UTF-8]
- uint32 flags
-
- where `id' is the request identifier, and `path' specifies the file
- system object for which status is to be returned. The server
- responds to this request with either SSH_FXP_ATTRS or SSH_FXP_STATUS.
-
- The flags field specify the attribute flags in which the client has
- particular interest. This is a hint to the server. For example,
- because retrieving owner / group and acl information can be an
- expensive operation under some operating systems, the server may
- choose not to retrieve this information unless the client expresses a
- specific interest in it.
-
- The client has no guarantee the server will provide all the fields
- that it has expressed an interest in.
-
- SSH_FXP_FSTAT differs from the others in that it returns status
- information for an open file (identified by the file handle). Its
- format is as follows:
-
- uint32 id
- string handle
- uint32 flags
-
- where `id' is the request identifier and `handle' is a file handle
- returned by SSH_FXP_OPEN. The server responds to this request with
- SSH_FXP_ATTRS or SSH_FXP_STATUS.
-
-6.9 Setting File Attributes
-
- File attributes may be modified using the SSH_FXP_SETSTAT and
- SSH_FXP_FSETSTAT requests. These requests are used for operations
- such as changing the ownership, permissions or access times, as well
- as for truncating a file.
-
- The SSH_FXP_SETSTAT request is of the following format:
-
- uint32 id
- string path [UTF-8]
- ATTRS attrs
-
- where `id' is the request identifier, `path' specifies the file
- system object (e.g. file or directory) whose attributes are to be
-
-
-
-Galbraith, et al. Expires April 16, 2003 [Page 21]
-
-Internet-Draft SSH File Transfer Protocol October 2002
-
-
- modified, and `attrs' specifies the modifications to be made to its
- attributes. Attributes are discussed in more detail in Section
- ``File Attributes''.
-
- An error will be returned if the specified file system object does
- not exist or the user does not have sufficient rights to modify the
- specified attributes. The server responds to this request with a
- SSH_FXP_STATUS message.
-
- The SSH_FXP_FSETSTAT request modifies the attributes of a file which
- is already open. It has the following format:
-
- uint32 id
- string handle
- ATTRS attrs
-
- where `id' is the request identifier, `handle' (MUST be returned by
- SSH_FXP_OPEN) identifies the file whose attributes are to be
- modified, and `attrs' specifies the modifications to be made to its
- attributes. Attributes are discussed in more detail in Section
- ``File Attributes''. The server will respond to this request with
- SSH_FXP_STATUS.
-
-6.10 Dealing with Symbolic links
-
- The SSH_FXP_READLINK request may be used to read the target of a
- symbolic link. It would have a data part as follows:
-
- uint32 id
- string path [UTF-8]
-
- where `id' is the request identifier and `path' specifies the path
- name of the symlink to be read.
-
- The server will respond with a SSH_FXP_NAME packet containing only
- one name and a dummy attributes value. The name in the returned
- packet contains the target of the link. If an error occurs, the
- server may respond with SSH_FXP_STATUS.
-
- The SSH_FXP_SYMLINK request will create a symbolic link on the
- server. It is of the following format
-
- uint32 id
- string linkpath [UTF-8]
- string targetpath [UTF-8]
-
- where `id' is the request identifier, `linkpath' specifies the path
- name of the symlink to be created and `targetpath' specifies the
-
-
-
-Galbraith, et al. Expires April 16, 2003 [Page 22]
-
-Internet-Draft SSH File Transfer Protocol October 2002
-
-
- target of the symlink. The server shall respond with a
- SSH_FXP_STATUS indicating either success (SSH_FX_OK) or an error
- condition.
-
-6.11 Canonicalizing the Server-Side Path Name
-
- The SSH_FXP_REALPATH request can be used to have the server
- canonicalize any given path name to an absolute path. This is useful
- for converting path names containing ".." components or relative
- pathnames without a leading slash into absolute paths. The format of
- the request is as follows:
-
- uint32 id
- string path [UTF-8]
-
- where `id' is the request identifier and `path' specifies the path
- name to be canonicalized. The server will respond with a
- SSH_FXP_NAME packet containing the name in canonical form and a dummy
- attributes value. If an error occurs, the server may also respond
- with SSH_FXP_STATUS.
-
-6.11.1 Best practice for dealing with paths
-
- The client SHOULD treat the results of SSH_FXP_REALPATH as a
- canonical absolute path, even if the path does not appear to be
- absolute. A client that use REALPATH(".") and treats the result as
- absolute, even if there is no leading slash, will continue to
- function correctly, even when talking to a Windows NT or VMS style
- system, where absolute paths may not begin with a slash.
-
- For example, if the client wishes to change directory up, and the
- server has returned "c:/x/y/z" from REALPATH, the client SHOULD use
- "c:/x/y/z/..".
-
- As a second example, if the client wishes to open the file "x.txt" in
- the current directory, and server has returned "dka100:/x/y/z" as the
- canonical path of the directory, the client SHOULD open "dka100:/x/y/
- z/x.txt"
-
-
-
-
-
-
-
-
-
-
-
-
-
-Galbraith, et al. Expires April 16, 2003 [Page 23]
-
-Internet-Draft SSH File Transfer Protocol October 2002
-
-
-7. Responses from the Server to the Client
-
- The server responds to the client using one of a few response
- packets. All requests can return a SSH_FXP_STATUS response upon
- failure. When the operation is successful, any of the responses may
- be returned (depending on the operation). If no data needs to be
- returned to the client, the SSH_FXP_STATUS response with SSH_FX_OK
- status is appropriate. Otherwise, the SSH_FXP_HANDLE message is used
- to return a file handle (for SSH_FXP_OPEN and SSH_FXP_OPENDIR
- requests), SSH_FXP_DATA is used to return data from SSH_FXP_READ,
- SSH_FXP_NAME is used to return one or more file names from a
- SSH_FXP_READDIR or SSH_FXP_REALPATH request, and SSH_FXP_ATTRS is
- used to return file attributes from SSH_FXP_STAT, SSH_FXP_LSTAT, and
- SSH_FXP_FSTAT requests.
-
- Exactly one response will be returned for each request. Each
- response packet contains a request identifier which can be used to
- match each response with the corresponding request. Note that it is
- legal to have several requests outstanding simultaneously, and the
- server is allowed to send responses to them in a different order from
- the order in which the requests were sent (the result of their
- execution, however, is guaranteed to be as if they had been processed
- one at a time in the order in which the requests were sent).
-
- Response packets are of the same general format as request packets.
- Each response packet begins with the request identifier.
-
- The format of the data portion of the SSH_FXP_STATUS response is as
- follows:
-
- uint32 id
- uint32 error/status code
- string error message (ISO-10646 UTF-8 [RFC-2279])
- string language tag (as defined in [RFC-1766])
-
- where `id' is the request identifier, and `error/status code'
- indicates the result of the requested operation. The value SSH_FX_OK
- indicates success, and all other values indicate failure.
-
- Currently, the following values are defined (other values may be
- defined by future versions of this protocol):
-
-
-
-
-
-
-
-
-
-
-Galbraith, et al. Expires April 16, 2003 [Page 24]
-
-Internet-Draft SSH File Transfer Protocol October 2002
-
-
- #define SSH_FX_OK 0
- #define SSH_FX_EOF 1
- #define SSH_FX_NO_SUCH_FILE 2
- #define SSH_FX_PERMISSION_DENIED 3
- #define SSH_FX_FAILURE 4
- #define SSH_FX_BAD_MESSAGE 5
- #define SSH_FX_NO_CONNECTION 6
- #define SSH_FX_CONNECTION_LOST 7
- #define SSH_FX_OP_UNSUPPORTED 8
- #define SSH_FX_INVALID_HANDLE 9
- #define SSH_FX_NO_SUCH_PATH 10
- #define SSH_FX_FILE_ALREADY_EXISTS 11
- #define SSH_FX_WRITE_PROTECT 12
-
- SSH_FX_OK
- Indicates successful completion of the operation.
-
- SSH_FX_EOF
- indicates end-of-file condition; for SSH_FX_READ it means that no
- more data is available in the file, and for SSH_FX_READDIR it
- indicates that no more files are contained in the directory.
-
- SSH_FX_NO_SUCH_FILE
- is returned when a reference is made to a file which does not
- exist.
-
- SSH_FX_PERMISSION_DENIED
- is returned when the authenticated user does not have sufficient
- permissions to perform the operation.
-
- SSH_FX_FAILURE
- is a generic catch-all error message; it should be returned if an
- error occurs for which there is no more specific error code
- defined.
-
- SSH_FX_BAD_MESSAGE
- may be returned if a badly formatted packet or protocol
- incompatibility is detected.
-
- SSH_FX_NO_CONNECTION
- is a pseudo-error which indicates that the client has no
- connection to the server (it can only be generated locally by the
- client, and MUST NOT be returned by servers).
-
- SSH_FX_CONNECTION_LOST
- is a pseudo-error which indicates that the connection to the
- server has been lost (it can only be generated locally by the
- client, and MUST NOT be returned by servers).
-
-
-
-Galbraith, et al. Expires April 16, 2003 [Page 25]
-
-Internet-Draft SSH File Transfer Protocol October 2002
-
-
- SSH_FX_OP_UNSUPPORTED
- indicates that an attempt was made to perform an operation which
- is not supported for the server (it may be generated locally by
- the client if e.g. the version number exchange indicates that a
- required feature is not supported by the server, or it may be
- returned by the server if the server does not implement an
- operation).
-
- SSH_FX_INVALID_HANDLE
- The handle value was invalid.
-
- SSH_FX_NO_SUCH_PATH
- The file path does not exist or is invalid.
-
- SSH_FX_FILE_ALREADY_EXISTS
- The file already exists.
-
- SSH_FX_WRITE_PROTECT
- The file is on read only media, or the media is write protected.
-
- The SSH_FXP_HANDLE response has the following format:
-
- uint32 id
- string handle
-
- where `id' is the request identifier, and `handle' is an arbitrary
- string that identifies an open file or directory on the server. The
- handle is opaque to the client; the client MUST NOT attempt to
- interpret or modify it in any way. The length of the handle string
- MUST NOT exceed 256 data bytes.
-
- The SSH_FXP_DATA response has the following format:
-
- uint32 id
- string data
-
- where `id' is the request identifier, and `data' is an arbitrary byte
- string containing the requested data. The data string may be at most
- the number of bytes requested in a SSH_FXP_READ request, but may also
- be shorter if end of file is reached or if the read is from something
- other than a regular file.
-
- The SSH_FXP_NAME response has the following format:
-
-
-
-
-
-
-
-
-Galbraith, et al. Expires April 16, 2003 [Page 26]
-
-Internet-Draft SSH File Transfer Protocol October 2002
-
-
- uint32 id
- uint32 count
- repeats count times:
- string filename [UTF-8]
- ATTRS attrs
-
- where `id' is the request identifier, `count' is the number of names
- returned in this response, and the remaining fields repeat `count'
- times (so that all three fields are first included for the first
- file, then for the second file, etc). In the repeated part,
- `filename' is a file name being returned (for SSH_FXP_READDIR, it
- will be a relative name within the directory, without any path
- components; for SSH_FXP_REALPATH it will be an absolute path name),
- and `attrs' is the attributes of the file as described in Section
- ``File Attributes''.
-
- The SSH_FXP_ATTRS response has the following format:
-
- uint32 id
- ATTRS attrs
-
- where `id' is the request identifier, and `attrs' is the returned
- file attributes as described in Section ``File Attributes''.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Galbraith, et al. Expires April 16, 2003 [Page 27]
-
-Internet-Draft SSH File Transfer Protocol October 2002
-
-
-8. Vendor-Specific Extensions
-
- The SSH_FXP_EXTENDED request provides a generic extension mechanism
- for adding vendor-specific commands. The request has the following
- format:
-
- uint32 id
- string extended-request
- ... any request-specific data ...
-
- where `id' is the request identifier, and `extended-request' is a
- string of the format "name@domain", where domain is an internet
- domain name of the vendor defining the request. The rest of the
- request is completely vendor-specific, and servers should only
- attempt to interpret it if they recognize the `extended-request'
- name.
-
- The server may respond to such requests using any of the response
- packets defined in Section ``Responses from the Server to the
- Client''. Additionally, the server may also respond with a
- SSH_FXP_EXTENDED_REPLY packet, as defined below. If the server does
- not recognize the `extended-request' name, then the server MUST
- respond with SSH_FXP_STATUS with error/status set to
- SSH_FX_OP_UNSUPPORTED.
-
- The SSH_FXP_EXTENDED_REPLY packet can be used to carry arbitrary
- extension-specific data from the server to the client. It is of the
- following format:
-
- uint32 id
- ... any request-specific data ...
-
- There is a range of packet types reserved for use by extensions. In
- order to avoid collision, extensions that turn on the use of
- additional packet types should determine those numbers dynamically.
-
- The suggested way of doing this is have an extension request from the
- client to the server that enables the extension; the extension
- response from the server to the client would specify the actual type
- values to use, in additional to any other data.
-
- Extension authors should be mindful of the limited range of packet
- types available (there are only 45 values available) and avoid
- requiring a new packet type where possible.
-
-
-
-
-
-
-
-Galbraith, et al. Expires April 16, 2003 [Page 28]
-
-Internet-Draft SSH File Transfer Protocol October 2002
-
-
-9. Security Considerations
-
- This protocol assumes that it is run over a secure channel and that
- the endpoints of the channel have been authenticated. Thus, this
- protocol assumes that it is externally protected from network-level
- attacks.
-
- This protocol provides file system access to arbitrary files on the
- server (only constrained by the server implementation). It is the
- responsibility of the server implementation to enforce any access
- controls that may be required to limit the access allowed for any
- particular user (the user being authenticated externally to this
- protocol, typically using the SSH User Authentication Protocol [8].
-
- Care must be taken in the server implementation to check the validity
- of received file handle strings. The server should not rely on them
- directly; it MUST check the validity of each handle before relying on
- it.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Galbraith, et al. Expires April 16, 2003 [Page 29]
-
-Internet-Draft SSH File Transfer Protocol October 2002
-
-
-10. Changes from previous protocol versions
-
- The SSH File Transfer Protocol has changed over time, before it's
- standardization. The following is a description of the incompatible
- changes between different versions.
-
-10.1 Changes between versions 4 and 3
-
- Many of the changes between version 4 and version 3 are to the
- attribute structure to make it more flexible for non-unix platforms.
-
- o Make all filenames UTF-8.
-
- o Added 'newline' extension.
-
- o Made file attribute owner and group strings so they can actually
- be used on disparate systems.
-
- o Added createtime field, and added separate flags for atime,
- createtime, and mtime so they can be set separately.
-
- o Split the file type out of the permissions field and into it's own
- field (which is always present.)
-
- o Added acl attribute.
-
- o Added SSH_FXF_TEXT file open flag.
-
- o Added flags field to the get stat commands so that the client can
- specifically request information the server might not normally
- included for performance reasons.
-
- o Removed the long filename from the names structure-- it can now be
- built from information available in the attrs structure.
-
- o Added reserved range of packet numbers for extensions.
-
- o Added several additional error codes.
-
- o Change the way version negotiate works slightly. Previously, if
- the client version were higher than the server version, the server
- was supposed to 'echo back' the clients version. The server now
- sends it's own version and the lower of the two is considered to
- be the one in use.
-
-
-
-
-
-
-
-Galbraith, et al. Expires April 16, 2003 [Page 30]
-
-Internet-Draft SSH File Transfer Protocol October 2002
-
-
-10.2 Changes between versions 3 and 2
-
- o The SSH_FXP_READLINK and SSH_FXP_SYMLINK messages were added.
-
- o The SSH_FXP_EXTENDED and SSH_FXP_EXTENDED_REPLY messages were
- added.
-
- o The SSH_FXP_STATUS message was changed to include fields `error
- message' and `language tag'.
-
-
-10.3 Changes between versions 2 and 1
-
- o The SSH_FXP_RENAME message was added.
-
-
-10.4 Changes between versions 1 and 0
-
- o Implementation changes, no actual protocol changes.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Galbraith, et al. Expires April 16, 2003 [Page 31]
-
-Internet-Draft SSH File Transfer Protocol October 2002
-
-
-11. Trademark Issues
-
- "ssh" is a registered trademark of SSH Communications Security Corp
- in the United States and/or other countries.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Galbraith, et al. Expires April 16, 2003 [Page 32]
-
-Internet-Draft SSH File Transfer Protocol October 2002
-
-
-References
-
- [1] Dierks, T., Allen, C., Treese, W., Karlton, P., Freier, A. and
- P. Kocher, "The TLS Protocol Version 1.0", RFC 2246, January
- 1999.
-
- [2] Alvestrand, H., "IETF Policy on Character Sets and Languages",
- BCP 18, RFC 2277, January 1998.
-
- [3] Shepler, S., Callaghan, B., Robinson, D., Thurlow, R., Beame,
- C., Eisler, M. and D. Noveck, "NFS version 4 Protocol", RFC
- 3010, December 2000.
-
- [4] Institute of Electrical and Electronics Engineers, "Information
- Technology - Portable Operating System Interface (POSIX) - Part
- 1: System Application Program Interface (API) [C Language]",
- IEEE Standard 1003.2, 1996.
-
- [5] Rinne, T., Ylonen, T., Kivinen, T., Saarinen, M. and S.
- Lehtinen, "SSH Protocol Architecture", draft-ietf-secsh-
- architecture-13 (work in progress), September 2002.
-
- [6] Rinne, T., Ylonen, T., Kivinen, T., Saarinen, M. and S.
- Lehtinen, "SSH Protocol Transport Protocol", draft-ietf-secsh-
- transport-15 (work in progress), September 2002.
-
- [7] Rinne, T., Ylonen, T., Kivinen, T., Saarinen, M. and S.
- Lehtinen, "SSH Connection Protocol", draft-ietf-secsh-connect-16
- (work in progress), September 2002.
-
- [8] Rinne, T., Ylonen, T., Kivinen, T., Saarinen, M. and S.
- Lehtinen, "SSH Authentication Protocol", draft-ietf-secsh-
- userauth-16 (work in progress), September 2002.
-
-
-Authors' Addresses
-
- Joseph Galbraith
- VanDyke Software
- 4848 Tramway Ridge Blvd
- Suite 101
- Albuquerque, NM 87111
- US
-
- Phone: +1 505 332 5700
-
-
-
-
-
-Galbraith, et al. Expires April 16, 2003 [Page 33]
-
-Internet-Draft SSH File Transfer Protocol October 2002
-
-
- Tatu Ylonen
- SSH Communications Security Corp
- Fredrikinkatu 42
- HELSINKI FIN-00100
- Finland
-
-
-
- Sami Lehtinen
- SSH Communications Security Corp
- Fredrikinkatu 42
- HELSINKI FIN-00100
- Finland
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Galbraith, et al. Expires April 16, 2003 [Page 34]
-
-Internet-Draft SSH File Transfer Protocol October 2002
-
-
-Full Copyright Statement
-
- Copyright (C) The Internet Society (2002). All Rights Reserved.
-
- This document and translations of it may be copied and furnished to
- others, and derivative works that comment on or otherwise explain it
- or assist in its implementation may be prepared, copied, published
- and distributed, in whole or in part, without restriction of any
- kind, provided that the above copyright notice and this paragraph are
- included on all such copies and derivative works. However, this
- document itself may not be modified in any way, such as by removing
- the copyright notice or references to the Internet Society or other
- Internet organizations, except as needed for the purpose of
- developing Internet standards in which case the procedures for
- copyrights defined in the Internet Standards process must be
- followed, or as required to translate it into languages other than
- English.
-
- The limited permissions granted above are perpetual and will not be
- revoked by the Internet Society or its successors or assigns.
-
- This document and the information contained herein is provided on an
- "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
- TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
- BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
- HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
- MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
-
-Acknowledgement
-
- Funding for the RFC Editor function is currently provided by the
- Internet Society.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Galbraith, et al. Expires April 16, 2003 [Page 35]
-
-
diff --git a/lib/ssh/doc/standard/draft-ietf-secsh-filexfer-04.txt b/lib/ssh/doc/standard/draft-ietf-secsh-filexfer-04.txt
deleted file mode 100644
index 9f51883cd2..0000000000
--- a/lib/ssh/doc/standard/draft-ietf-secsh-filexfer-04.txt
+++ /dev/null
@@ -1,2130 +0,0 @@
-
-
-
-Secure Shell Working Group J. Galbraith
-Internet-Draft VanDyke Software
-Expires: June 18, 2003 T. Ylonen
- S. Lehtinen
- SSH Communications Security Corp
- December 18, 2002
-
-
- SSH File Transfer Protocol
- draft-ietf-secsh-filexfer-04.txt
-
-Status of this Memo
-
- This document is an Internet-Draft and is in full conformance with
- all provisions of Section 10 of RFC2026.
-
- Internet-Drafts are working documents of the Internet Engineering
- Task Force (IETF), its areas, and its working groups. Note that
- other groups may also distribute working documents as
- Internet-Drafts.
-
- Internet-Drafts are draft documents valid for a maximum of six months
- and may be updated, replaced, or obsoleted by other documents at any
- time. It is inappropriate to use Internet-Drafts as reference
- material or to cite them other than as "work in progress."
-
- The list of current Internet-Drafts can be accessed at http://
- www.ietf.org/ietf/1id-abstracts.txt.
-
- The list of Internet-Draft Shadow Directories can be accessed at
- http://www.ietf.org/shadow.html.
-
- This Internet-Draft will expire on June 18, 2003.
-
-Copyright Notice
-
- Copyright (C) The Internet Society (2002). All Rights Reserved.
-
-Abstract
-
- The SSH File Transfer Protocol provides secure file transfer
- functionality over any reliable data stream. It is the standard file
- transfer protocol for use with the SSH2 protocol. This document
- describes the file transfer protocol and its interface to the SSH2
- protocol suite.
-
-
-
-
-
-
-
-Galbraith, et al. Expires June 18, 2003 [Page 1]
-
-Internet-Draft SSH File Transfer Protocol December 2002
-
-
-Table of Contents
-
- 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . 3
- 2. Use with the SSH Connection Protocol . . . . . . . . . . . 4
- 3. General Packet Format . . . . . . . . . . . . . . . . . . 5
- 3.1 The use of stderr in the server . . . . . . . . . . . . . 6
- 4. Protocol Initialization . . . . . . . . . . . . . . . . . 8
- 4.1 Client Initialization . . . . . . . . . . . . . . . . . . 8
- 4.2 Server Initialization . . . . . . . . . . . . . . . . . . 8
- 4.3 Determining Server Newline Convention . . . . . . . . . . 9
- 5. File Attributes . . . . . . . . . . . . . . . . . . . . . 10
- 5.1 Flags . . . . . . . . . . . . . . . . . . . . . . . . . . 10
- 5.2 Type . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
- 5.3 Size . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
- 5.4 Owner and Group . . . . . . . . . . . . . . . . . . . . . 11
- 5.5 Permissions . . . . . . . . . . . . . . . . . . . . . . . 12
- 5.6 Times . . . . . . . . . . . . . . . . . . . . . . . . . . 12
- 5.7 ACL . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
- 5.8 Extended attributes . . . . . . . . . . . . . . . . . . . 14
- 6. Requests From the Client to the Server . . . . . . . . . . 15
- 6.1 Request Synchronization and Reordering . . . . . . . . . . 15
- 6.2 File Names . . . . . . . . . . . . . . . . . . . . . . . . 16
- 6.3 Opening, Creating, and Closing Files . . . . . . . . . . . 16
- 6.4 Reading and Writing . . . . . . . . . . . . . . . . . . . 19
- 6.5 Removing and Renaming Files . . . . . . . . . . . . . . . 20
- 6.6 Creating and Deleting Directories . . . . . . . . . . . . 21
- 6.7 Scanning Directories . . . . . . . . . . . . . . . . . . . 21
- 6.8 Retrieving File Attributes . . . . . . . . . . . . . . . . 22
- 6.9 Setting File Attributes . . . . . . . . . . . . . . . . . 23
- 6.10 Dealing with Symbolic links . . . . . . . . . . . . . . . 24
- 6.11 Canonicalizing the Server-Side Path Name . . . . . . . . . 25
- 6.11.1 Best practice for dealing with paths . . . . . . . . . . . 25
- 7. Responses from the Server to the Client . . . . . . . . . 26
- 8. Vendor-Specific Extensions . . . . . . . . . . . . . . . . 30
- 9. Security Considerations . . . . . . . . . . . . . . . . . 31
- 10. Changes from previous protocol versions . . . . . . . . . 32
- 10.1 Changes between versions 4 and 3 . . . . . . . . . . . . . 32
- 10.2 Changes between versions 3 and 2 . . . . . . . . . . . . . 33
- 10.3 Changes between versions 2 and 1 . . . . . . . . . . . . . 33
- 10.4 Changes between versions 1 and 0 . . . . . . . . . . . . . 33
- 11. Trademark Issues . . . . . . . . . . . . . . . . . . . . . 34
- References . . . . . . . . . . . . . . . . . . . . . . . . 35
- Authors' Addresses . . . . . . . . . . . . . . . . . . . . 35
- Intellectual Property and Copyright Statements . . . . . . 37
-
-
-
-
-
-
-
-Galbraith, et al. Expires June 18, 2003 [Page 2]
-
-Internet-Draft SSH File Transfer Protocol December 2002
-
-
-1. Introduction
-
- This protocol provides secure file transfer (and more generally file
- system access) functionality over a reliable data stream, such as a
- channel in the SSH2 protocol [5].
-
- This protocol is designed so that it could be used to implement a
- secure remote file system service, as well as a secure file transfer
- service.
-
- This protocol assumes that it runs over a secure channel, and that
- the server has already authenticated the user at the client end, and
- that the identity of the client user is externally available to the
- server implementation.
-
- In general, this protocol follows a simple request-response model.
- Each request and response contains a sequence number and multiple
- requests may be pending simultaneously. There are a relatively large
- number of different request messages, but a small number of possible
- response messages. Each request has one or more response messages
- that may be returned in result (e.g., a read either returns data or
- reports error status).
-
- The packet format descriptions in this specification follow the
- notation presented in the secsh architecture draft. [5]
-
- Even though this protocol is described in the context of the SSH2
- protocol, this protocol is general and independent of the rest of the
- SSH2 protocol suite. It could be used in a number of different
- applications, such as secure file transfer over TLS RFC 2246 [1] and
- transfer of management information in VPN applications.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Galbraith, et al. Expires June 18, 2003 [Page 3]
-
-Internet-Draft SSH File Transfer Protocol December 2002
-
-
-2. Use with the SSH Connection Protocol
-
- When used with the SSH2 Protocol suite, this protocol is intended to
- be used from the SSH Connection Protocol [7] as a subsystem, as
- described in section ``Starting a Shell or a Command''. The
- subsystem name used with this protocol is "sftp".
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Galbraith, et al. Expires June 18, 2003 [Page 4]
-
-Internet-Draft SSH File Transfer Protocol December 2002
-
-
-3. General Packet Format
-
- All packets transmitted over the secure connection are of the
- following format:
-
- uint32 length
- byte type
- byte[length - 1] data payload
-
- That is, they are just data preceded by 32-bit length and 8-bit type
- fields. The `length' is the length of the data area, and does not
- include the `length' field itself. The format and interpretation of
- the data area depends on the packet type.
-
- All packet descriptions below only specify the packet type and the
- data that goes into the data field. Thus, they should be prefixed by
- the `length' and `type' fields.
-
- The maximum size of a packet is in practice determined by the client
- (the maximum size of read or write requests that it sends, plus a few
- bytes of packet overhead). All servers SHOULD support packets of at
- least 34000 bytes (where the packet size refers to the full length,
- including the header above). This should allow for reads and writes
- of at most 32768 bytes.
-
- There is no limit on the number of outstanding (non-acknowledged)
- requests that the client may send to the server. In practice this is
- limited by the buffering available on the data stream and the queuing
- performed by the server. If the server's queues are full, it should
- not read any more data from the stream, and flow control will prevent
- the client from sending more requests. Note, however, that while
- there is no restriction on the protocol level, the client's API may
- provide a limit in order to prevent infinite queuing of outgoing
- requests at the client.
-
- The following values are defined for packet types.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Galbraith, et al. Expires June 18, 2003 [Page 5]
-
-Internet-Draft SSH File Transfer Protocol December 2002
-
-
- #define SSH_FXP_INIT 1
- #define SSH_FXP_VERSION 2
- #define SSH_FXP_OPEN 3
- #define SSH_FXP_CLOSE 4
- #define SSH_FXP_READ 5
- #define SSH_FXP_WRITE 6
- #define SSH_FXP_LSTAT 7
- #define SSH_FXP_FSTAT 8
- #define SSH_FXP_SETSTAT 9
- #define SSH_FXP_FSETSTAT 10
- #define SSH_FXP_OPENDIR 11
- #define SSH_FXP_READDIR 12
- #define SSH_FXP_REMOVE 13
- #define SSH_FXP_MKDIR 14
- #define SSH_FXP_RMDIR 15
- #define SSH_FXP_REALPATH 16
- #define SSH_FXP_STAT 17
- #define SSH_FXP_RENAME 18
- #define SSH_FXP_READLINK 19
- #define SSH_FXP_SYMLINK 20
-
- #define SSH_FXP_STATUS 101
- #define SSH_FXP_HANDLE 102
- #define SSH_FXP_DATA 103
- #define SSH_FXP_NAME 104
- #define SSH_FXP_ATTRS 105
-
- #define SSH_FXP_EXTENDED 200
- #define SSH_FXP_EXTENDED_REPLY 201
-
- RESERVED_FOR_EXTENSIONS 210-255
-
- Additional packet types should only be defined if the protocol
- version number (see Section ``Protocol Initialization'') is
- incremented, and their use MUST be negotiated using the version
- number. However, the SSH_FXP_EXTENDED and SSH_FXP_EXTENDED_REPLY
- packets can be used to implement vendor-specific extensions. See
- Section ``Vendor-Specific-Extensions'' for more details.
-
-3.1 The use of stderr in the server
-
- Packets are sent and received on stdout and stdin. Data sent on
- stderr by the server SHOULD be considered debug or supplemental error
- information, and MAY be displayed to the user.
-
- For example, during initialization, there is no client request
- active, so errors or warning information cannot be sent to the client
- as part of the SFTP protocol at this early stage. However, the
-
-
-
-Galbraith, et al. Expires June 18, 2003 [Page 6]
-
-Internet-Draft SSH File Transfer Protocol December 2002
-
-
- errors or warnings MAY be sent as stderr text.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Galbraith, et al. Expires June 18, 2003 [Page 7]
-
-Internet-Draft SSH File Transfer Protocol December 2002
-
-
-4. Protocol Initialization
-
- When the file transfer protocol starts, the client first sends a
- SSH_FXP_INIT (including its version number) packet to the server.
- The server responds with a SSH_FXP_VERSION packet, supplying the
- lowest of its own and the client's version number. Both parties
- should from then on adhere to particular version of the protocol.
-
- The version number of the protocol specified in this document is 4.
- The version number should be incremented for each incompatible
- revision of this protocol.
-
-4.1 Client Initialization
-
- The SSH_FXP_INIT packet (from client to server) has the following
- data:
-
- uint32 version
-
- Version 3 of this protocol allowed clients to include extensions in
- the SSH_FXP_INIT packet; however, this can cause interoperability
- problems with version 1 and version 2 servers because the client must
- send this packet before knowing the servers version.
-
- In this version of the protocol, clients MUST use the
- SSH_FXP_EXTENDED packet to send extensions to the server after
- version exchange has completed. Clients MUST NOT include extensions
- in the version packet. This will prevent interoperability problems
- with older servers
-
-4.2 Server Initialization
-
- The SSH_FXP_VERSION packet (from server to client) has the following
- data:
-
- uint32 version
- <extension data>
-
- 'version' is the lower of the protocol version supported by the
- server and the version number received from the client.
-
- The extension data may be empty, or may be a sequence of
-
- string extension_name
- string extension_data
-
- pairs (both strings MUST always be present if one is, but the
- `extension_data' string may be of zero length). If present, these
-
-
-
-Galbraith, et al. Expires June 18, 2003 [Page 8]
-
-Internet-Draft SSH File Transfer Protocol December 2002
-
-
- strings indicate extensions to the baseline protocol. The
- `extension_name' field(s) identify the name of the extension. The
- name should be of the form "name@domain", where the domain is the DNS
- domain name of the organization defining the extension. Additional
- names that are not of this format may be defined later by the IETF.
- Implementations MUST silently ignore any extensions whose name they
- do not recognize.
-
-4.3 Determining Server Newline Convention
-
- In order to correctly process text files in a cross platform
- compatible way, the newline convention must be converted from that of
- the server to that of the client, or, during an upload, from that of
- the client to that of the server.
-
- Versions 3 and prior of this protocol made no provisions for
- processing text files. Many clients implemented some sort of
- conversion algorithm, but without either a 'canonical' on the wire
- format or knowledge of the servers newline convention, correct
- conversion was not always possible.
-
- Starting with Version 4, the SSH_FXF_TEXT file open flag (Section
- 6.3) makes it possible to request that the server translate a file to
- a 'canonical' on the wire format. This format uses \r\n as the line
- separator.
-
- Servers for systems using multiple newline characters (for example,
- Mac OS X or VMS) or systems using counted records, MUST translate to
- the canonical form.
-
- However, to ease the burden of implementation on servers that use a
- single, simple separator sequence, the following extension allows the
- canonical format to be changed.
-
- string "newline"
- string new-canonical-separator (usually "\r" or "\n" or "\r\n")
-
- All clients MUST support this extension.
-
- When processing text files, clients SHOULD NOT translate any
- character or sequence that is not an exact match of the servers
- newline separator.
-
- In particular, if the newline sequence being used is the canonical
- "\r\n" sequence, a lone \r or a lone \n SHOULD be written through
- without change.
-
-
-
-
-
-Galbraith, et al. Expires June 18, 2003 [Page 9]
-
-Internet-Draft SSH File Transfer Protocol December 2002
-
-
-5. File Attributes
-
- A new compound data type is defined for encoding file attributes.
- The same encoding is used both when returning file attributes from
- the server and when sending file attributes to the server. When
- sending it to the server, the flags field specifies which attributes
- are included, and the server will use default values for the
- remaining attributes (or will not modify the values of remaining
- attributes). When receiving attributes from the server, the flags
- specify which attributes are included in the returned data. The
- server normally returns all attributes it knows about.
-
- uint32 flags
- byte type always present
- uint64 size present only if flag SIZE
- string owner present only if flag OWNERGROUP
- string group present only if flag OWNERGROUP
- uint32 permissions present only if flag PERMISSIONS
- uint64 atime present only if flag ACCESSTIME
- uint32 atime_nseconds present only if flag SUBSECOND_TIMES
- uint64 createtime present only if flag CREATETIME
- uint32 createtime_nseconds present only if flag SUBSECOND_TIMES
- uint64 mtime present only if flag MODIFYTIME
- uint32 mtime_nseconds present only if flag SUBSECOND_TIMES
- string acl present only if flag ACL
- uint32 extended_count present only if flag EXTENDED
- string extended_type
- string extended_data
- ... more extended data (extended_type - extended_data pairs),
- so that number of pairs equals extended_count
-
-
-5.1 Flags
-
- The `flags' specify which of the fields are present. Those fields
- for which the corresponding flag is not set are not present (not
- included in the packet). New flags can only be added by incrementing
- the protocol version number (or by using the extension mechanism
- described below).
-
- The flags bits are defined to have the following values:
-
-
-
-
-
-
-
-
-
-
-Galbraith, et al. Expires June 18, 2003 [Page 10]
-
-Internet-Draft SSH File Transfer Protocol December 2002
-
-
- #define SSH_FILEXFER_ATTR_SIZE 0x00000001
- #define SSH_FILEXFER_ATTR_PERMISSIONS 0x00000040
- #define SSH_FILEXFER_ATTR_ACCESSTIME 0x00000008
- #define SSH_FILEXFER_ATTR_CREATETIME 0x00000010
- #define SSH_FILEXFER_ATTR_MODIFYTIME 0x00000020
- #define SSH_FILEXFER_ATTR_ACL 0x00000040
- #define SSH_FILEXFER_ATTR_OWNERGROUP 0x00000080
- #define SSH_FILEXFER_ATTR_SUBSECOND_TIMES 0x00000100
- #define SSH_FILEXFER_ATTR_EXTENDED 0x80000000
-
- In previous versions of this protocol flags value 0x00000002 was
- SSH_FILEXFER_ATTR_UIDGID. This value is now unused, and OWNERGROUP
- was given a new value in order to ease implementation burden.
- 0x00000002 MUST NOT appear in the mask. Some future version of this
- protocol may reuse flag 0x00000002.
-
-5.2 Type
-
- The type field is always present. The following types are defined:
-
- #define SSH_FILEXFER_TYPE_REGULAR 1
- #define SSH_FILEXFER_TYPE_DIRECTORY 2
- #define SSH_FILEXFER_TYPE_SYMLINK 3
- #define SSH_FILEXFER_TYPE_SPECIAL 4
- #define SSH_FILEXFER_TYPE_UNKNOWN 5
-
- On a POSIX system, these values would be derived from the permission
- field.
-
-5.3 Size
-
- The `size' field specifies the size of the file on disk, in bytes.
- If it is present during file creation, it should be considered a hint
- as to the files eventual size.
-
- Files opened with the SSH_FXF_TEXT flag may have a size that is
- greater or less than the value of the size field.
-
-5.4 Owner and Group
-
- The `owner' and `group' fields are represented as UTF-8 strings; this
- is the form used by NFS v4. See NFS version 4 Protocol. [3] The
- following text is selected quotations from section 5.6.
-
- To avoid a representation that is tied to a particular underlying
- implementation at the client or server, the use of UTF-8 strings has
- been chosen. The string should be of the form user@dns_domain".
- This will allow for a client and server that do not use the same
-
-
-
-Galbraith, et al. Expires June 18, 2003 [Page 11]
-
-Internet-Draft SSH File Transfer Protocol December 2002
-
-
- local representation the ability to translate to a common syntax that
- can be interpreted by both. In the case where there is no
- translation available to the client or server, the attribute value
- must be constructed without the "@". Therefore, the absence of the @
- from the owner or owner_group attribute signifies that no translation
- was available and the receiver of the attribute should not place any
- special meaning with the attribute value. Even though the attribute
- value can not be translated, it may still be useful. In the case of
- a client, the attribute string may be used for local display of
- ownership.
-
-5.5 Permissions
-
- The `permissions' field contains a bit mask of file permissions as
- defined by POSIX [1].
-
-5.6 Times
-
- The 'atime', 'createtime', and 'mtime' contain the access, creation,
- and modification times of the files, respectively. They are
- represented as seconds from Jan 1, 1970 in UTC.
-
- A negative value indicates number of seconds before Jan 1, 1970. In
- both cases, if the SSH_FILEXFER_ATTR_SUBSECOND_TIMES flag is set, the
- nseconds field is to be added to the seconds field for the final time
- representation. For example, if the time to be represented is
- one-half second before 0 hour January 1, 1970, the seconds field
- would have a value of negative one (-1) and the nseconds fields would
- have a value of one-half second (500000000). Values greater than
- 999,999,999 for nseconds are considered invalid.
-
-5.7 ACL
-
- The 'ACL' field contains an ACL similar to that defined in section
- 5.9 of NFS version 4 Protocol [3].
-
- uint32 ace-count
-
- repeated ace-count time:
- uint32 ace-type
- uint32 ace-flag
- uint32 ace-mask
- string who [UTF-8]
-
- ace-type is one of the following four values (taken from NFS Version
- 4 Protocol [3]:
-
-
-
-
-
-Galbraith, et al. Expires June 18, 2003 [Page 12]
-
-Internet-Draft SSH File Transfer Protocol December 2002
-
-
- const ACE4_ACCESS_ALLOWED_ACE_TYPE = 0x00000000;
- const ACE4_ACCESS_DENIED_ACE_TYPE = 0x00000001;
- const ACE4_SYSTEM_AUDIT_ACE_TYPE = 0x00000002;
- const ACE4_SYSTEM_ALARM_ACE_TYPE = 0x00000003;
-
- ace-flag is a combination of the following flag values. See NFS
- Version 4 Protocol [3] section 5.9.2:
-
- const ACE4_FILE_INHERIT_ACE = 0x00000001;
- const ACE4_DIRECTORY_INHERIT_ACE = 0x00000002;
- const ACE4_NO_PROPAGATE_INHERIT_ACE = 0x00000004;
- const ACE4_INHERIT_ONLY_ACE = 0x00000008;
- const ACE4_SUCCESSFUL_ACCESS_ACE_FLAG = 0x00000010;
- const ACE4_FAILED_ACCESS_ACE_FLAG = 0x00000020;
- const ACE4_IDENTIFIER_GROUP = 0x00000040;
-
- ace-mask is any combination of the following flags (taken from NFS
- Version 4 Protocol [3] section 5.9.3:
-
- const ACE4_READ_DATA = 0x00000001;
- const ACE4_LIST_DIRECTORY = 0x00000001;
- const ACE4_WRITE_DATA = 0x00000002;
- const ACE4_ADD_FILE = 0x00000002;
- const ACE4_APPEND_DATA = 0x00000004;
- const ACE4_ADD_SUBDIRECTORY = 0x00000004;
- const ACE4_READ_NAMED_ATTRS = 0x00000008;
- const ACE4_WRITE_NAMED_ATTRS = 0x00000010;
- const ACE4_EXECUTE = 0x00000020;
- const ACE4_DELETE_CHILD = 0x00000040;
- const ACE4_READ_ATTRIBUTES = 0x00000080;
- const ACE4_WRITE_ATTRIBUTES = 0x00000100;
- const ACE4_DELETE = 0x00010000;
- const ACE4_READ_ACL = 0x00020000;
- const ACE4_WRITE_ACL = 0x00040000;
- const ACE4_WRITE_OWNER = 0x00080000;
- const ACE4_SYNCHRONIZE = 0x00100000;
-
- who is a UTF-8 string of the form described in 'Owner and Group'
- (Section 5.4)
-
- Also, as per '5.9.4 ACE who' [3] there are several identifiers that
- need to be understood universally. Some of these identifiers cannot
- be understood when an client access the server, but have meaning when
- a local process accesses the file. The ability to display and modify
- these permissions is permitted over SFTP.
-
- OWNER The owner of the file.
-
-
-
-
-Galbraith, et al. Expires June 18, 2003 [Page 13]
-
-Internet-Draft SSH File Transfer Protocol December 2002
-
-
- GROUP The group associated with the file.
-
- EVERYONE The world.
-
- INTERACTIVE Accessed from an interactive terminal.
-
- NETWORK Accessed via the network.
-
- DIALUP Accessed as a dialup user to the server.
-
- BATCH Accessed from a batch job.
-
- ANONYMOUS Accessed without any authentication.
-
- AUTHENTICATED Any authenticated user (opposite of ANONYMOUS).
-
- SERVICE Access from a system service.
-
- To avoid conflict, these special identifiers are distinguish by an
- appended "@" and should appear in the form "xxxx@" (note: no domain
- name after the "@"). For example: ANONYMOUS@.
-
-5.8 Extended attributes
-
- The SSH_FILEXFER_ATTR_EXTENDED flag provides a general extension
- mechanism for vendor-specific extensions. If the flag is specified,
- then the `extended_count' field is present. It specifies the number
- of extended_type-extended_data pairs that follow. Each of these
- pairs specifies an extended attribute. For each of the attributes,
- the extended_type field should be a string of the format
- "name@domain", where "domain" is a valid, registered domain name and
- "name" identifies the method. The IETF may later standardize certain
- names that deviate from this format (e.g., that do not contain the
- "@" sign). The interpretation of `extended_data' depends on the
- type. Implementations SHOULD ignore extended data fields that they
- do not understand.
-
- Additional fields can be added to the attributes by either defining
- additional bits to the flags field to indicate their presence, or by
- defining extended attributes for them. The extended attributes
- mechanism is recommended for most purposes; additional flags bits
- should only be defined by an IETF standards action that also
- increments the protocol version number. The use of such new fields
- MUST be negotiated by the version number in the protocol exchange.
- It is a protocol error if a packet with unsupported protocol bits is
- received.
-
-
-
-
-
-Galbraith, et al. Expires June 18, 2003 [Page 14]
-
-Internet-Draft SSH File Transfer Protocol December 2002
-
-
-6. Requests From the Client to the Server
-
- Requests from the client to the server represent the various file
- system operations. Each request begins with an `id' field, which is
- a 32-bit identifier identifying the request (selected by the client).
- The same identifier will be returned in the response to the request.
- One possible implementation is a monotonically increasing request
- sequence number (modulo 2^32).
-
- Many operations in the protocol operate on open files. The
- SSH_FXP_OPEN request can return a file handle (which is an opaque
- variable-length string) which may be used to access the file later
- (e.g. in a read operation). The client MUST NOT send requests the
- server with bogus or closed handles. However, the server MUST
- perform adequate checks on the handle in order to avoid security
- risks due to fabricated handles.
-
- This design allows either stateful and stateless server
- implementation, as well as an implementation which caches state
- between requests but may also flush it. The contents of the file
- handle string are entirely up to the server and its design. The
- client should not modify or attempt to interpret the file handle
- strings.
-
- The file handle strings MUST NOT be longer than 256 bytes.
-
-6.1 Request Synchronization and Reordering
-
- The protocol and implementations MUST process requests relating to
- the same file in the order in which they are received. In other
- words, if an application submits multiple requests to the server, the
- results in the responses will be the same as if it had sent the
- requests one at a time and waited for the response in each case. For
- example, the server may process non-overlapping read/write requests
- to the same file in parallel, but overlapping reads and writes cannot
- be reordered or parallelized. However, there are no ordering
- restrictions on the server for processing requests from two different
- file transfer connections. The server may interleave and parallelize
- them at will.
-
- There are no restrictions on the order in which responses to
- outstanding requests are delivered to the client, except that the
- server must ensure fairness in the sense that processing of no
- request will be indefinitely delayed even if the client is sending
- other requests so that there are multiple outstanding requests all
- the time.
-
-
-
-
-
-Galbraith, et al. Expires June 18, 2003 [Page 15]
-
-Internet-Draft SSH File Transfer Protocol December 2002
-
-
-6.2 File Names
-
- This protocol represents file names as strings. File names are
- assumed to use the slash ('/') character as a directory separator.
-
- File names starting with a slash are "absolute", and are relative to
- the root of the file system. Names starting with any other character
- are relative to the user's default directory (home directory). Note
- that identifying the user is assumed to take place outside of this
- protocol.
-
- Servers SHOULD interpret a path name component ".." as referring to
- the parent directory, and "." as referring to the current directory.
- If the server implementation limits access to certain parts of the
- file system, it must be extra careful in parsing file names when
- enforcing such restrictions. There have been numerous reported
- security bugs where a ".." in a path name has allowed access outside
- the intended area.
-
- An empty path name is valid, and it refers to the user's default
- directory (usually the user's home directory).
-
- Otherwise, no syntax is defined for file names by this specification.
- Clients should not make any other assumptions; however, they can
- splice path name components returned by SSH_FXP_READDIR together
- using a slash ('/') as the separator, and that will work as expected.
-
- In order to comply with IETF Policy on Character Sets and Languages
- [2], all filenames are to be encoded in UTF-8. The shortest valid
- UTF-8 encoding of the UNICODE data MUST be used. The server is
- responsible for converting the UNICODE data to whatever canonical
- form it requires.
-
- For example, if the server requires that precomposed characters
- always be used, the server MUST NOT assume the filename as sent by
- the client has this attribute, but must do this normalization itself.
-
- It is understood that the lack of well-defined semantics for file
- names may cause interoperability problems between clients and servers
- using radically different operating systems. However, this approach
- is known to work acceptably with most systems, and alternative
- approaches that e.g. treat file names as sequences of structured
- components are quite complicated.
-
-6.3 Opening, Creating, and Closing Files
-
- Files are opened and created using the SSH_FXP_OPEN message, whose
- data part is as follows:
-
-
-
-Galbraith, et al. Expires June 18, 2003 [Page 16]
-
-Internet-Draft SSH File Transfer Protocol December 2002
-
-
- uint32 id
- string filename [UTF-8]
- uint32 pflags
- ATTRS attrs
-
- The `id' field is the request identifier as for all requests.
-
- The `filename' field specifies the file name. See Section ``File
- Names'' for more information.
-
- The `pflags' field is a bitmask. The following bits have been
- defined.
-
- #define SSH_FXF_READ 0x00000001
- #define SSH_FXF_WRITE 0x00000002
- #define SSH_FXF_APPEND 0x00000004
- #define SSH_FXF_CREAT 0x00000008
- #define SSH_FXF_TRUNC 0x00000010
- #define SSH_FXF_EXCL 0x00000020
- #define SSH_FXF_TEXT 0x00000040
-
- These have the following meanings:
-
- SSH_FXF_READ
- Open the file for reading.
-
- SSH_FXF_WRITE
- Open the file for writing. If both this and SSH_FXF_READ are
- specified, the file is opened for both reading and writing.
-
- SSH_FXF_APPEND
- Force all writes to append data at the end of the file. The
- offset parameter to write will be ignored.
-
- SSH_FXF_CREAT
- If this flag is specified, then a new file will be created if one
- does not already exist (if O_TRUNC is specified, the new file will
- be truncated to zero length if it previously exists).
-
- SSH_FXF_TRUNC
- Forces an existing file with the same name to be truncated to zero
- length when creating a file by specifying SSH_FXF_CREAT.
- SSH_FXF_CREAT MUST also be specified if this flag is used.
-
- SSH_FXF_EXCL
- Causes the request to fail if the named file already exists.
- SSH_FXF_CREAT MUST also be specified if this flag is used.
-
-
-
-
-Galbraith, et al. Expires June 18, 2003 [Page 17]
-
-Internet-Draft SSH File Transfer Protocol December 2002
-
-
- SSH_FXF_TEXT
- Indicates that the server should treat the file as text and
- convert it to the canonical newline convention in use. (See
- Determining Server Newline Convention. (Section 4.3)
-
- When a file is opened with the FXF_TEXT flag, the offset field in
- both the read and write function are ignored.
-
- Servers MUST correctly process multiple parallel reads and writes
- correctly in this mode. Naturally, it is permissible for them to
- do this by serializing the requests. It would not be possible for
- a client to reliably detect a server that does not implement
- parallel writes in time to prevent damage.
-
- Clients SHOULD use the SSH_FXF_APPEND flag to append data to a
- text file rather then using write with a calculated offset.
-
- To support seeks on text file the following SSH_FXP_EXTENDED
- packet is defined.
-
-
-
- string "text-seek"
- string file-handle
- uint64 line-number
-
- line-number is the index of the line number to seek to, where byte
- 0 in the file is line number 0, and the byte directly following
- the first newline sequence in the file is line number 1 and so on.
-
- The response to a "text-seek" request is an SSH_FXP_STATUS
- message.
-
- An attempt to seek past the end-of-file should result in a
- SSH_FX_EOF status.
-
- Servers SHOULD support at least one "text-seek" in order to
- support resume. However, a client MUST be prepared to receive
- SSH_FX_OP_UNSUPPORTED when attempting a "text-seek" operation.
- The client can then try a fall-back strategy, if it has one.
-
- Clients MUST be prepared to handle SSH_FX_OP_UNSUPPORTED returned
- for read or write operations that are not sequential.
-
- The `attrs' field specifies the initial attributes for the file.
- Default values will be used for those attributes that are not
- specified. See Section ``File Attributes'' for more information.
-
-
-
-
-Galbraith, et al. Expires June 18, 2003 [Page 18]
-
-Internet-Draft SSH File Transfer Protocol December 2002
-
-
- The response to this message will be either SSH_FXP_HANDLE (if the
- operation is successful) or SSH_FXP_STATUS (if the operation fails).
-
- A file is closed by using the SSH_FXP_CLOSE request. Its data field
- has the following format:
-
- uint32 id
- string handle
-
- where `id' is the request identifier, and `handle' is a handle
- previously returned in the response to SSH_FXP_OPEN or
- SSH_FXP_OPENDIR. The handle becomes invalid immediately after this
- request has been sent.
-
- The response to this request will be a SSH_FXP_STATUS message. One
- should note that on some server platforms even a close can fail.
- This can happen e.g. if the server operating system caches writes,
- and an error occurs while flushing cached writes during the close.
-
-6.4 Reading and Writing
-
- Once a file has been opened, it can be read using the following
- message:
-
- byte SSH_FXP_READ
- uint32 id
- string handle
- uint64 offset
- uint32 len
-
- where `id' is the request identifier, `handle' is an open file handle
- returned by SSH_FXP_OPEN, `offset' is the offset (in bytes) relative
- to the beginning of the file from where to start reading, and `len'
- is the maximum number of bytes to read.
-
- In response to this request, the server will read as many bytes as it
- can from the file (up to `len'), and return them in a SSH_FXP_DATA
- message. If an error occurs or EOF is encountered before reading any
- data, the server will respond with SSH_FXP_STATUS.
-
- For normal disk files, it is normally guaranteed that this will read
- the specified number of bytes, or up to end of file. However, if the
- read length is very long, the server may truncate it if it doesn't
- support packets of that length. See General Packet Format (Section
- 3).
-
- For e.g. device files this may return fewer bytes than requested.
-
-
-
-
-Galbraith, et al. Expires June 18, 2003 [Page 19]
-
-Internet-Draft SSH File Transfer Protocol December 2002
-
-
- Writing to a file is achieved using the following message:
-
- byte SSH_FXP_WRITE
- uint32 id
- string handle
- uint64 offset
- string data
-
- where `id' is a request identifier, `handle' is a file handle
- returned by SSH_FXP_OPEN, `offset' is the offset (in bytes) from the
- beginning of the file where to start writing, and `data' is the data
- to be written.
-
- The write will extend the file if writing beyond the end of the file.
- It is legal to write way beyond the end of the file; the semantics
- are to write zeroes from the end of the file to the specified offset
- and then the data. On most operating systems, such writes do not
- allocate disk space but instead leave "holes" in the file.
-
- The server responds to a write request with a SSH_FXP_STATUS message.
-
-6.5 Removing and Renaming Files
-
- Files can be removed using the SSH_FXP_REMOVE message. It has the
- following format:
-
- uint32 id
- string filename [UTF-8]
-
- where `id' is the request identifier and `filename' is the name of
- the file to be removed. See Section ``File Names'' for more
- information. This request cannot be used to remove directories.
-
- The server will respond to this request with a SSH_FXP_STATUS
- message.
-
- Files (and directories) can be renamed using the SSH_FXP_RENAME
- message. Its data is as follows:
-
- uint32 id
- string oldpath [UTF-8]
- string newpath [UTF-8]
-
- where `id' is the request identifier, `oldpath' is the name of an
- existing file or directory, and `newpath' is the new name for the
- file or directory. It is an error if there already exists a file
- with the name specified by newpath. The server may also fail rename
- requests in other situations, for example if `oldpath' and `newpath'
-
-
-
-Galbraith, et al. Expires June 18, 2003 [Page 20]
-
-Internet-Draft SSH File Transfer Protocol December 2002
-
-
- point to different file systems on the server.
-
- The server will respond to this request with a SSH_FXP_STATUS
- message.
-
-6.6 Creating and Deleting Directories
-
- New directories can be created using the SSH_FXP_MKDIR request. It
- has the following format:
-
- uint32 id
- string path [UTF-8]
- ATTRS attrs
-
- where `id' is the request identifier.
-
- `path' specifies the directory to be created. See Section ``File
- Names'' for more information on file names.
-
- `attrs' specifies the attributes that should be applied to it upon
- creation. Attributes are discussed in more detail in Section ``File
- Attributes''.
-
- The server will respond to this request with a SSH_FXP_STATUS
- message. If a file or directory with the specified path already
- exists, an error will be returned.
-
- Directories can be removed using the SSH_FXP_RMDIR request, which has
- the following format:
-
- uint32 id
- string path [UTF-8]
-
- where `id' is the request identifier, and `path' specifies the
- directory to be removed. See Section ``File Names'' for more
- information on file names.
-
- The server responds to this request with a SSH_FXP_STATUS message.
- Errors may be returned from this operation for various reasons,
- including, but not limited to, the path does not exist, the path does
- not refer to a directory object, the directory is not empty, or the
- user has insufficient access or permission to perform the requested
- operation.
-
-6.7 Scanning Directories
-
- The files in a directory can be listed using the SSH_FXP_OPENDIR and
- SSH_FXP_READDIR requests. Each SSH_FXP_READDIR request returns one
-
-
-
-Galbraith, et al. Expires June 18, 2003 [Page 21]
-
-Internet-Draft SSH File Transfer Protocol December 2002
-
-
- or more file names with full file attributes for each file. The
- client should call SSH_FXP_READDIR repeatedly until it has found the
- file it is looking for or until the server responds with a
- SSH_FXP_STATUS message indicating an error (normally SSH_FX_EOF if
- there are no more files in the directory). The client should then
- close the handle using the SSH_FXP_CLOSE request.
-
- The SSH_FXP_OPENDIR opens a directory for reading. It has the
- following format:
-
- uint32 id
- string path [UTF-8]
-
- where `id' is the request identifier and `path' is the path name of
- the directory to be listed (without any trailing slash). See Section
- ``File Names'' for more information on file names. This will return
- an error if the path does not specify a directory or if the directory
- is not readable. The server will respond to this request with either
- a SSH_FXP_HANDLE or a SSH_FXP_STATUS message.
-
- Once the directory has been successfully opened, files (and
- directories) contained in it can be listed using SSH_FXP_READDIR
- requests. These are of the format
-
- uint32 id
- string handle
-
- where `id' is the request identifier, and `handle' is a handle
- returned by SSH_FXP_OPENDIR. (It is a protocol error to attempt to
- use an ordinary file handle returned by SSH_FXP_OPEN.)
-
- The server responds to this request with either a SSH_FXP_NAME or a
- SSH_FXP_STATUS message. One or more names may be returned at a time.
- Full status information is returned for each name in order to speed
- up typical directory listings.
-
- If there are no more names available to be read, the server MUST
- respond with a SSH_FXP_STATUS message with error code of SSH_FX_EOF.
-
- When the client no longer wishes to read more names from the
- directory, it SHOULD call SSH_FXP_CLOSE for the handle. The handle
- should be closed regardless of whether an error has occurred or not.
-
-6.8 Retrieving File Attributes
-
- Very often, file attributes are automatically returned by
- SSH_FXP_READDIR. However, sometimes there is need to specifically
- retrieve the attributes for a named file. This can be done using the
-
-
-
-Galbraith, et al. Expires June 18, 2003 [Page 22]
-
-Internet-Draft SSH File Transfer Protocol December 2002
-
-
- SSH_FXP_STAT, SSH_FXP_LSTAT and SSH_FXP_FSTAT requests.
-
- SSH_FXP_STAT and SSH_FXP_LSTAT only differ in that SSH_FXP_STAT
- follows symbolic links on the server, whereas SSH_FXP_LSTAT does not
- follow symbolic links. Both have the same format:
-
- uint32 id
- string path [UTF-8]
- uint32 flags
-
- where `id' is the request identifier, and `path' specifies the file
- system object for which status is to be returned. The server
- responds to this request with either SSH_FXP_ATTRS or SSH_FXP_STATUS.
-
- The flags field specify the attribute flags in which the client has
- particular interest. This is a hint to the server. For example,
- because retrieving owner / group and acl information can be an
- expensive operation under some operating systems, the server may
- choose not to retrieve this information unless the client expresses a
- specific interest in it.
-
- The client has no guarantee the server will provide all the fields
- that it has expressed an interest in.
-
- SSH_FXP_FSTAT differs from the others in that it returns status
- information for an open file (identified by the file handle). Its
- format is as follows:
-
- uint32 id
- string handle
- uint32 flags
-
- where `id' is the request identifier and `handle' is a file handle
- returned by SSH_FXP_OPEN. The server responds to this request with
- SSH_FXP_ATTRS or SSH_FXP_STATUS.
-
-6.9 Setting File Attributes
-
- File attributes may be modified using the SSH_FXP_SETSTAT and
- SSH_FXP_FSETSTAT requests. These requests are used for operations
- such as changing the ownership, permissions or access times, as well
- as for truncating a file.
-
- The SSH_FXP_SETSTAT request is of the following format:
-
-
-
-
-
-
-
-Galbraith, et al. Expires June 18, 2003 [Page 23]
-
-Internet-Draft SSH File Transfer Protocol December 2002
-
-
- uint32 id
- string path [UTF-8]
- ATTRS attrs
-
- where `id' is the request identifier, `path' specifies the file
- system object (e.g. file or directory) whose attributes are to be
- modified, and `attrs' specifies the modifications to be made to its
- attributes. Attributes are discussed in more detail in Section
- ``File Attributes''.
-
- An error will be returned if the specified file system object does
- not exist or the user does not have sufficient rights to modify the
- specified attributes. The server responds to this request with a
- SSH_FXP_STATUS message.
-
- The SSH_FXP_FSETSTAT request modifies the attributes of a file which
- is already open. It has the following format:
-
- uint32 id
- string handle
- ATTRS attrs
-
- where `id' is the request identifier, `handle' (MUST be returned by
- SSH_FXP_OPEN) identifies the file whose attributes are to be
- modified, and `attrs' specifies the modifications to be made to its
- attributes. Attributes are discussed in more detail in Section
- ``File Attributes''. The server will respond to this request with
- SSH_FXP_STATUS.
-
-6.10 Dealing with Symbolic links
-
- The SSH_FXP_READLINK request may be used to read the target of a
- symbolic link. It would have a data part as follows:
-
- uint32 id
- string path [UTF-8]
-
- where `id' is the request identifier and `path' specifies the path
- name of the symlink to be read.
-
- The server will respond with a SSH_FXP_NAME packet containing only
- one name and a dummy attributes value. The name in the returned
- packet contains the target of the link. If an error occurs, the
- server may respond with SSH_FXP_STATUS.
-
- The SSH_FXP_SYMLINK request will create a symbolic link on the
- server. It is of the following format
-
-
-
-
-Galbraith, et al. Expires June 18, 2003 [Page 24]
-
-Internet-Draft SSH File Transfer Protocol December 2002
-
-
- uint32 id
- string linkpath [UTF-8]
- string targetpath [UTF-8]
-
- where `id' is the request identifier, `linkpath' specifies the path
- name of the symlink to be created and `targetpath' specifies the
- target of the symlink. The server shall respond with a
- SSH_FXP_STATUS indicating either success (SSH_FX_OK) or an error
- condition.
-
-6.11 Canonicalizing the Server-Side Path Name
-
- The SSH_FXP_REALPATH request can be used to have the server
- canonicalize any given path name to an absolute path. This is useful
- for converting path names containing ".." components or relative
- pathnames without a leading slash into absolute paths. The format of
- the request is as follows:
-
- uint32 id
- string path [UTF-8]
-
- where `id' is the request identifier and `path' specifies the path
- name to be canonicalized. The server will respond with a
- SSH_FXP_NAME packet containing the name in canonical form and a dummy
- attributes value. If an error occurs, the server may also respond
- with SSH_FXP_STATUS.
-
-6.11.1 Best practice for dealing with paths
-
- The client SHOULD treat the results of SSH_FXP_REALPATH as a
- canonical absolute path, even if the path does not appear to be
- absolute. A client that use REALPATH(".") and treats the result as
- absolute, even if there is no leading slash, will continue to
- function correctly, even when talking to a Windows NT or VMS style
- system, where absolute paths may not begin with a slash.
-
- For example, if the client wishes to change directory up, and the
- server has returned "c:/x/y/z" from REALPATH, the client SHOULD use
- "c:/x/y/z/..".
-
- As a second example, if the client wishes to open the file "x.txt" in
- the current directory, and server has returned "dka100:/x/y/z" as the
- canonical path of the directory, the client SHOULD open "dka100:/x/y/
- z/x.txt"
-
-
-
-
-
-
-
-Galbraith, et al. Expires June 18, 2003 [Page 25]
-
-Internet-Draft SSH File Transfer Protocol December 2002
-
-
-7. Responses from the Server to the Client
-
- The server responds to the client using one of a few response
- packets. All requests can return a SSH_FXP_STATUS response upon
- failure. When the operation is successful, any of the responses may
- be returned (depending on the operation). If no data needs to be
- returned to the client, the SSH_FXP_STATUS response with SSH_FX_OK
- status is appropriate. Otherwise, the SSH_FXP_HANDLE message is used
- to return a file handle (for SSH_FXP_OPEN and SSH_FXP_OPENDIR
- requests), SSH_FXP_DATA is used to return data from SSH_FXP_READ,
- SSH_FXP_NAME is used to return one or more file names from a
- SSH_FXP_READDIR or SSH_FXP_REALPATH request, and SSH_FXP_ATTRS is
- used to return file attributes from SSH_FXP_STAT, SSH_FXP_LSTAT, and
- SSH_FXP_FSTAT requests.
-
- Exactly one response will be returned for each request. Each
- response packet contains a request identifier which can be used to
- match each response with the corresponding request. Note that it is
- legal to have several requests outstanding simultaneously, and the
- server is allowed to send responses to them in a different order from
- the order in which the requests were sent (the result of their
- execution, however, is guaranteed to be as if they had been processed
- one at a time in the order in which the requests were sent).
-
- Response packets are of the same general format as request packets.
- Each response packet begins with the request identifier.
-
- The format of the data portion of the SSH_FXP_STATUS response is as
- follows:
-
- uint32 id
- uint32 error/status code
- string error message (ISO-10646 UTF-8 [RFC-2279])
- string language tag (as defined in [RFC-1766])
-
- where `id' is the request identifier, and `error/status code'
- indicates the result of the requested operation. The value SSH_FX_OK
- indicates success, and all other values indicate failure.
-
- Currently, the following values are defined (other values may be
- defined by future versions of this protocol):
-
-
-
-
-
-
-
-
-
-
-Galbraith, et al. Expires June 18, 2003 [Page 26]
-
-Internet-Draft SSH File Transfer Protocol December 2002
-
-
- #define SSH_FX_OK 0
- #define SSH_FX_EOF 1
- #define SSH_FX_NO_SUCH_FILE 2
- #define SSH_FX_PERMISSION_DENIED 3
- #define SSH_FX_FAILURE 4
- #define SSH_FX_BAD_MESSAGE 5
- #define SSH_FX_NO_CONNECTION 6
- #define SSH_FX_CONNECTION_LOST 7
- #define SSH_FX_OP_UNSUPPORTED 8
- #define SSH_FX_INVALID_HANDLE 9
- #define SSH_FX_NO_SUCH_PATH 10
- #define SSH_FX_FILE_ALREADY_EXISTS 11
- #define SSH_FX_WRITE_PROTECT 12
- #define SSH_FX_NO_MEDIA 13
-
- SSH_FX_OK
- Indicates successful completion of the operation.
-
- SSH_FX_EOF
- indicates end-of-file condition; for SSH_FX_READ it means that no
- more data is available in the file, and for SSH_FX_READDIR it
- indicates that no more files are contained in the directory.
-
- SSH_FX_NO_SUCH_FILE
- is returned when a reference is made to a file which does not
- exist.
-
- SSH_FX_PERMISSION_DENIED
- is returned when the authenticated user does not have sufficient
- permissions to perform the operation.
-
- SSH_FX_FAILURE
- is a generic catch-all error message; it should be returned if an
- error occurs for which there is no more specific error code
- defined.
-
- SSH_FX_BAD_MESSAGE
- may be returned if a badly formatted packet or protocol
- incompatibility is detected.
-
- SSH_FX_NO_CONNECTION
- is a pseudo-error which indicates that the client has no
- connection to the server (it can only be generated locally by the
- client, and MUST NOT be returned by servers).
-
- SSH_FX_CONNECTION_LOST
- is a pseudo-error which indicates that the connection to the
- server has been lost (it can only be generated locally by the
-
-
-
-Galbraith, et al. Expires June 18, 2003 [Page 27]
-
-Internet-Draft SSH File Transfer Protocol December 2002
-
-
- client, and MUST NOT be returned by servers).
-
- SSH_FX_OP_UNSUPPORTED
- indicates that an attempt was made to perform an operation which
- is not supported for the server (it may be generated locally by
- the client if e.g. the version number exchange indicates that a
- required feature is not supported by the server, or it may be
- returned by the server if the server does not implement an
- operation).
-
- SSH_FX_INVALID_HANDLE
- The handle value was invalid.
-
- SSH_FX_NO_SUCH_PATH
- The file path does not exist or is invalid.
-
- SSH_FX_FILE_ALREADY_EXISTS
- The file already exists.
-
- SSH_FX_WRITE_PROTECT
- The file is on read only media, or the media is write protected.
-
- SSH_FX_NO_MEDIA
- The requested operation can not be completed because there is no
- media available in the drive.
-
- The SSH_FXP_HANDLE response has the following format:
-
- uint32 id
- string handle
-
- where `id' is the request identifier, and `handle' is an arbitrary
- string that identifies an open file or directory on the server. The
- handle is opaque to the client; the client MUST NOT attempt to
- interpret or modify it in any way. The length of the handle string
- MUST NOT exceed 256 data bytes.
-
- The SSH_FXP_DATA response has the following format:
-
- uint32 id
- string data
-
- where `id' is the request identifier, and `data' is an arbitrary byte
- string containing the requested data. The data string may be at most
- the number of bytes requested in a SSH_FXP_READ request, but may also
- be shorter if end of file is reached or if the read is from something
- other than a regular file.
-
-
-
-
-Galbraith, et al. Expires June 18, 2003 [Page 28]
-
-Internet-Draft SSH File Transfer Protocol December 2002
-
-
- The SSH_FXP_NAME response has the following format:
-
- uint32 id
- uint32 count
- repeats count times:
- string filename [UTF-8]
- ATTRS attrs
-
- where `id' is the request identifier, `count' is the number of names
- returned in this response, and the remaining fields repeat `count'
- times (so that all three fields are first included for the first
- file, then for the second file, etc). In the repeated part,
- `filename' is a file name being returned (for SSH_FXP_READDIR, it
- will be a relative name within the directory, without any path
- components; for SSH_FXP_REALPATH it will be an absolute path name),
- and `attrs' is the attributes of the file as described in Section
- ``File Attributes''.
-
- The SSH_FXP_ATTRS response has the following format:
-
- uint32 id
- ATTRS attrs
-
- where `id' is the request identifier, and `attrs' is the returned
- file attributes as described in Section ``File Attributes''.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Galbraith, et al. Expires June 18, 2003 [Page 29]
-
-Internet-Draft SSH File Transfer Protocol December 2002
-
-
-8. Vendor-Specific Extensions
-
- The SSH_FXP_EXTENDED request provides a generic extension mechanism
- for adding vendor-specific commands. The request has the following
- format:
-
- uint32 id
- string extended-request
- ... any request-specific data ...
-
- where `id' is the request identifier, and `extended-request' is a
- string of the format "name@domain", where domain is an internet
- domain name of the vendor defining the request. The rest of the
- request is completely vendor-specific, and servers should only
- attempt to interpret it if they recognize the `extended-request'
- name.
-
- The server may respond to such requests using any of the response
- packets defined in Section ``Responses from the Server to the
- Client''. Additionally, the server may also respond with a
- SSH_FXP_EXTENDED_REPLY packet, as defined below. If the server does
- not recognize the `extended-request' name, then the server MUST
- respond with SSH_FXP_STATUS with error/status set to
- SSH_FX_OP_UNSUPPORTED.
-
- The SSH_FXP_EXTENDED_REPLY packet can be used to carry arbitrary
- extension-specific data from the server to the client. It is of the
- following format:
-
- uint32 id
- ... any request-specific data ...
-
- There is a range of packet types reserved for use by extensions. In
- order to avoid collision, extensions that turn on the use of
- additional packet types should determine those numbers dynamically.
-
- The suggested way of doing this is have an extension request from the
- client to the server that enables the extension; the extension
- response from the server to the client would specify the actual type
- values to use, in additional to any other data.
-
- Extension authors should be mindful of the limited range of packet
- types available (there are only 45 values available) and avoid
- requiring a new packet type where possible.
-
-
-
-
-
-
-
-Galbraith, et al. Expires June 18, 2003 [Page 30]
-
-Internet-Draft SSH File Transfer Protocol December 2002
-
-
-9. Security Considerations
-
- This protocol assumes that it is run over a secure channel and that
- the endpoints of the channel have been authenticated. Thus, this
- protocol assumes that it is externally protected from network-level
- attacks.
-
- This protocol provides file system access to arbitrary files on the
- server (only constrained by the server implementation). It is the
- responsibility of the server implementation to enforce any access
- controls that may be required to limit the access allowed for any
- particular user (the user being authenticated externally to this
- protocol, typically using the SSH User Authentication Protocol [8].
-
- Care must be taken in the server implementation to check the validity
- of received file handle strings. The server should not rely on them
- directly; it MUST check the validity of each handle before relying on
- it.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Galbraith, et al. Expires June 18, 2003 [Page 31]
-
-Internet-Draft SSH File Transfer Protocol December 2002
-
-
-10. Changes from previous protocol versions
-
- The SSH File Transfer Protocol has changed over time, before it's
- standardization. The following is a description of the incompatible
- changes between different versions.
-
-10.1 Changes between versions 4 and 3
-
- Many of the changes between version 4 and version 3 are to the
- attribute structure to make it more flexible for non-unix platforms.
-
- o Clarify the use of stderr by the server.
-
- o Clarify handling of very large read requests by the server.
-
- o Make all filenames UTF-8.
-
- o Added 'newline' extension.
-
- o Made time fields 64 bit, and optionally have nanosecond resultion.
-
- o Made file attribute owner and group strings so they can actually
- be used on disparate systems.
-
- o Added createtime field, and added separate flags for atime,
- createtime, and mtime so they can be set separately.
-
- o Split the file type out of the permissions field and into it's own
- field (which is always present.)
-
- o Added acl attribute.
-
- o Added SSH_FXF_TEXT file open flag.
-
- o Added flags field to the get stat commands so that the client can
- specifically request information the server might not normally
- included for performance reasons.
-
- o Removed the long filename from the names structure-- it can now be
- built from information available in the attrs structure.
-
- o Added reserved range of packet numbers for extensions.
-
- o Added several additional error codes.
-
-
-
-
-
-
-
-Galbraith, et al. Expires June 18, 2003 [Page 32]
-
-Internet-Draft SSH File Transfer Protocol December 2002
-
-
-10.2 Changes between versions 3 and 2
-
- o The SSH_FXP_READLINK and SSH_FXP_SYMLINK messages were added.
-
- o The SSH_FXP_EXTENDED and SSH_FXP_EXTENDED_REPLY messages were
- added.
-
- o The SSH_FXP_STATUS message was changed to include fields `error
- message' and `language tag'.
-
-
-10.3 Changes between versions 2 and 1
-
- o The SSH_FXP_RENAME message was added.
-
-
-10.4 Changes between versions 1 and 0
-
- o Implementation changes, no actual protocol changes.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Galbraith, et al. Expires June 18, 2003 [Page 33]
-
-Internet-Draft SSH File Transfer Protocol December 2002
-
-
-11. Trademark Issues
-
- "ssh" is a registered trademark of SSH Communications Security Corp
- in the United States and/or other countries.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Galbraith, et al. Expires June 18, 2003 [Page 34]
-
-Internet-Draft SSH File Transfer Protocol December 2002
-
-
-References
-
- [1] Dierks, T., Allen, C., Treese, W., Karlton, P., Freier, A. and
- P. Kocher, "The TLS Protocol Version 1.0", RFC 2246, January
- 1999.
-
- [2] Alvestrand, H., "IETF Policy on Character Sets and Languages",
- BCP 18, RFC 2277, January 1998.
-
- [3] Shepler, S., Callaghan, B., Robinson, D., Thurlow, R., Beame,
- C., Eisler, M. and D. Noveck, "NFS version 4 Protocol", RFC
- 3010, December 2000.
-
- [4] Institute of Electrical and Electronics Engineers, "Information
- Technology - Portable Operating System Interface (POSIX) - Part
- 1: System Application Program Interface (API) [C Language]",
- IEEE Standard 1003.2, 1996.
-
- [5] Rinne, T., Ylonen, T., Kivinen, T., Saarinen, M. and S.
- Lehtinen, "SSH Protocol Architecture",
- draft-ietf-secsh-architecture-13 (work in progress), September
- 2002.
-
- [6] Rinne, T., Ylonen, T., Kivinen, T., Saarinen, M. and S.
- Lehtinen, "SSH Protocol Transport Protocol",
- draft-ietf-secsh-transport-15 (work in progress), September
- 2002.
-
- [7] Rinne, T., Ylonen, T., Kivinen, T., Saarinen, M. and S.
- Lehtinen, "SSH Connection Protocol", draft-ietf-secsh-connect-16
- (work in progress), September 2002.
-
- [8] Rinne, T., Ylonen, T., Kivinen, T., Saarinen, M. and S.
- Lehtinen, "SSH Authentication Protocol",
- draft-ietf-secsh-userauth-16 (work in progress), September 2002.
-
-
-Authors' Addresses
-
- Joseph Galbraith
- VanDyke Software
- 4848 Tramway Ridge Blvd
- Suite 101
- Albuquerque, NM 87111
- US
-
- Phone: +1 505 332 5700
-
-
-
-Galbraith, et al. Expires June 18, 2003 [Page 35]
-
-Internet-Draft SSH File Transfer Protocol December 2002
-
-
- Tatu Ylonen
- SSH Communications Security Corp
- Fredrikinkatu 42
- HELSINKI FIN-00100
- Finland
-
-
-
- Sami Lehtinen
- SSH Communications Security Corp
- Fredrikinkatu 42
- HELSINKI FIN-00100
- Finland
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Galbraith, et al. Expires June 18, 2003 [Page 36]
-
-Internet-Draft SSH File Transfer Protocol December 2002
-
-
-Intellectual Property Statement
-
- The IETF takes no position regarding the validity or scope of any
- intellectual property or other rights that might be claimed to
- pertain to the implementation or use of the technology described in
- this document or the extent to which any license under such rights
- might or might not be available; neither does it represent that it
- has made any effort to identify any such rights. Information on the
- IETF's procedures with respect to rights in standards-track and
- standards-related documentation can be found in BCP-11. Copies of
- claims of rights made available for publication and any assurances of
- licenses to be made available, or the result of an attempt made to
- obtain a general license or permission for the use of such
- proprietary rights by implementors or users of this specification can
- be obtained from the IETF Secretariat.
-
- The IETF invites any interested party to bring to its attention any
- copyrights, patents or patent applications, or other proprietary
- rights which may cover technology that may be required to practice
- this standard. Please address the information to the IETF Executive
- Director.
-
-
-Full Copyright Statement
-
- Copyright (C) The Internet Society (2002). All Rights Reserved.
-
- This document and translations of it may be copied and furnished to
- others, and derivative works that comment on or otherwise explain it
- or assist in its implementation may be prepared, copied, published
- and distributed, in whole or in part, without restriction of any
- kind, provided that the above copyright notice and this paragraph are
- included on all such copies and derivative works. However, this
- document itself may not be modified in any way, such as by removing
- the copyright notice or references to the Internet Society or other
- Internet organizations, except as needed for the purpose of
- developing Internet standards in which case the procedures for
- copyrights defined in the Internet Standards process must be
- followed, or as required to translate it into languages other than
- English.
-
- The limited permissions granted above are perpetual and will not be
- revoked by the Internet Society or its successors or assignees.
-
- This document and the information contained herein is provided on an
- "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
- TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
- BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
-
-
-
-Galbraith, et al. Expires June 18, 2003 [Page 37]
-
-Internet-Draft SSH File Transfer Protocol December 2002
-
-
- HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
- MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
-
-
-Acknowledgement
-
- Funding for the RFC Editor function is currently provided by the
- Internet Society.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Galbraith, et al. Expires June 18, 2003 [Page 38]
-
-
diff --git a/lib/ssh/doc/standard/draft-ietf-secsh-transport-17.2.ps b/lib/ssh/doc/standard/draft-ietf-secsh-transport-17.2.ps
deleted file mode 100644
index d692285b4e..0000000000
--- a/lib/ssh/doc/standard/draft-ietf-secsh-transport-17.2.ps
+++ /dev/null
@@ -1,3205 +0,0 @@
-%!PS-Adobe-3.0
-%%BoundingBox: 75 0 595 747
-%%Title: Enscript Output
-%%For: Magnus Thoang
-%%Creator: GNU enscript 1.6.1
-%%CreationDate: Fri Oct 31 13:35:14 2003
-%%Orientation: Portrait
-%%Pages: 15 0
-%%DocumentMedia: A4 595 842 0 () ()
-%%DocumentNeededResources: (atend)
-%%EndComments
-%%BeginProlog
-%%BeginProcSet: PStoPS 1 15
-userdict begin
-[/showpage/erasepage/copypage]{dup where{pop dup load
- type/operatortype eq{1 array cvx dup 0 3 index cvx put
- bind def}{pop}ifelse}{pop}ifelse}forall
-[/letter/legal/executivepage/a4/a4small/b5/com10envelope
- /monarchenvelope/c5envelope/dlenvelope/lettersmall/note
- /folio/quarto/a5]{dup where{dup wcheck{exch{}put}
- {pop{}def}ifelse}{pop}ifelse}forall
-/setpagedevice {pop}bind 1 index where{dup wcheck{3 1 roll put}
- {pop def}ifelse}{def}ifelse
-/PStoPSmatrix matrix currentmatrix def
-/PStoPSxform matrix def/PStoPSclip{clippath}def
-/defaultmatrix{PStoPSmatrix exch PStoPSxform exch concatmatrix}bind def
-/initmatrix{matrix defaultmatrix setmatrix}bind def
-/initclip[{matrix currentmatrix PStoPSmatrix setmatrix
- [{currentpoint}stopped{$error/newerror false put{newpath}}
- {/newpath cvx 3 1 roll/moveto cvx 4 array astore cvx}ifelse]
- {[/newpath cvx{/moveto cvx}{/lineto cvx}
- {/curveto cvx}{/closepath cvx}pathforall]cvx exch pop}
- stopped{$error/errorname get/invalidaccess eq{cleartomark
- $error/newerror false put cvx exec}{stop}ifelse}if}bind aload pop
- /initclip dup load dup type dup/operatortype eq{pop exch pop}
- {dup/arraytype eq exch/packedarraytype eq or
- {dup xcheck{exch pop aload pop}{pop cvx}ifelse}
- {pop cvx}ifelse}ifelse
- {newpath PStoPSclip clip newpath exec setmatrix} bind aload pop]cvx def
-/initgraphics{initmatrix newpath initclip 1 setlinewidth
- 0 setlinecap 0 setlinejoin []0 setdash 0 setgray
- 10 setmiterlimit}bind def
-end
-%%EndProcSet
-%%BeginResource: procset Enscript-Prolog 1.6 1
-%
-% Procedures.
-%
-
-/_S { % save current state
- /_s save def
-} def
-/_R { % restore from saved state
- _s restore
-} def
-
-/S { % showpage protecting gstate
- gsave
- showpage
- grestore
-} bind def
-
-/MF { % fontname newfontname -> - make a new encoded font
- /newfontname exch def
- /fontname exch def
-
- /fontdict fontname findfont def
- /newfont fontdict maxlength dict def
-
- fontdict {
- exch
- dup /FID eq {
- % skip FID pair
- pop pop
- } {
- % copy to the new font dictionary
- exch newfont 3 1 roll put
- } ifelse
- } forall
-
- newfont /FontName newfontname put
-
- % insert only valid encoding vectors
- encoding_vector length 256 eq {
- newfont /Encoding encoding_vector put
- } if
-
- newfontname newfont definefont pop
-} def
-
-/SF { % fontname width height -> - set a new font
- /height exch def
- /width exch def
-
- findfont
- [width 0 0 height 0 0] makefont setfont
-} def
-
-/SUF { % fontname width height -> - set a new user font
- /height exch def
- /width exch def
-
- /F-gs-user-font MF
- /F-gs-user-font width height SF
-} def
-
-/M {moveto} bind def
-/s {show} bind def
-
-/Box { % x y w h -> - define box path
- /d_h exch def /d_w exch def /d_y exch def /d_x exch def
- d_x d_y moveto
- d_w 0 rlineto
- 0 d_h rlineto
- d_w neg 0 rlineto
- closepath
-} def
-
-/bgs { % x y height blskip gray str -> - show string with bg color
- /str exch def
- /gray exch def
- /blskip exch def
- /height exch def
- /y exch def
- /x exch def
-
- gsave
- x y blskip sub str stringwidth pop height Box
- gray setgray
- fill
- grestore
- x y M str s
-} def
-
-% Highlight bars.
-/highlight_bars { % nlines lineheight output_y_margin gray -> -
- gsave
- setgray
- /ymarg exch def
- /lineheight exch def
- /nlines exch def
-
- % This 2 is just a magic number to sync highlight lines to text.
- 0 d_header_y ymarg sub 2 sub translate
-
- /cw d_output_w cols div def
- /nrows d_output_h ymarg 2 mul sub lineheight div cvi def
-
- % for each column
- 0 1 cols 1 sub {
- cw mul /xp exch def
-
- % for each rows
- 0 1 nrows 1 sub {
- /rn exch def
- rn lineheight mul neg /yp exch def
- rn nlines idiv 2 mod 0 eq {
- % Draw highlight bar. 4 is just a magic indentation.
- xp 4 add yp cw 8 sub lineheight neg Box fill
- } if
- } for
- } for
-
- grestore
-} def
-
-% Line highlight bar.
-/line_highlight { % x y width height gray -> -
- gsave
- /gray exch def
- Box gray setgray fill
- grestore
-} def
-
-% Column separator lines.
-/column_lines {
- gsave
- .1 setlinewidth
- 0 d_footer_h translate
- /cw d_output_w cols div def
- 1 1 cols 1 sub {
- cw mul 0 moveto
- 0 d_output_h rlineto stroke
- } for
- grestore
-} def
-
-% Column borders.
-/column_borders {
- gsave
- .1 setlinewidth
- 0 d_footer_h moveto
- 0 d_output_h rlineto
- d_output_w 0 rlineto
- 0 d_output_h neg rlineto
- closepath stroke
- grestore
-} def
-
-% Do the actual underlay drawing
-/draw_underlay {
- ul_style 0 eq {
- ul_str true charpath stroke
- } {
- ul_str show
- } ifelse
-} def
-
-% Underlay
-/underlay { % - -> -
- gsave
- 0 d_page_h translate
- d_page_h neg d_page_w atan rotate
-
- ul_gray setgray
- ul_font setfont
- /dw d_page_h dup mul d_page_w dup mul add sqrt def
- ul_str stringwidth pop dw exch sub 2 div ul_h_ptsize -2 div moveto
- draw_underlay
- grestore
-} def
-
-/user_underlay { % - -> -
- gsave
- ul_x ul_y translate
- ul_angle rotate
- ul_gray setgray
- ul_font setfont
- 0 0 ul_h_ptsize 2 div sub moveto
- draw_underlay
- grestore
-} def
-
-% Page prefeed
-/page_prefeed { % bool -> -
- statusdict /prefeed known {
- statusdict exch /prefeed exch put
- } {
- pop
- } ifelse
-} def
-
-% Wrapped line markers
-/wrapped_line_mark { % x y charwith charheight type -> -
- /type exch def
- /h exch def
- /w exch def
- /y exch def
- /x exch def
-
- type 2 eq {
- % Black boxes (like TeX does)
- gsave
- 0 setlinewidth
- x w 4 div add y M
- 0 h rlineto w 2 div 0 rlineto 0 h neg rlineto
- closepath fill
- grestore
- } {
- type 3 eq {
- % Small arrows
- gsave
- .2 setlinewidth
- x w 2 div add y h 2 div add M
- w 4 div 0 rlineto
- x w 4 div add y lineto stroke
-
- x w 4 div add w 8 div add y h 4 div add M
- x w 4 div add y lineto
- w 4 div h 8 div rlineto stroke
- grestore
- } {
- % do nothing
- } ifelse
- } ifelse
-} def
-
-% EPSF import.
-
-/BeginEPSF {
- /b4_Inc_state save def % Save state for cleanup
- /dict_count countdictstack def % Count objects on dict stack
- /op_count count 1 sub def % Count objects on operand stack
- userdict begin
- /showpage { } def
- 0 setgray 0 setlinecap
- 1 setlinewidth 0 setlinejoin
- 10 setmiterlimit [ ] 0 setdash newpath
- /languagelevel where {
- pop languagelevel
- 1 ne {
- false setstrokeadjust false setoverprint
- } if
- } if
-} bind def
-
-/EndEPSF {
- count op_count sub { pos } repeat % Clean up stacks
- countdictstack dict_count sub { end } repeat
- b4_Inc_state restore
-} bind def
-
-% Check PostScript language level.
-/languagelevel where {
- pop /gs_languagelevel languagelevel def
-} {
- /gs_languagelevel 1 def
-} ifelse
-%%EndResource
-%%BeginResource: procset Enscript-Encoding-88591 1.6 1
-/encoding_vector [
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/space /exclam /quotedbl /numbersign
-/dollar /percent /ampersand /quoteright
-/parenleft /parenright /asterisk /plus
-/comma /hyphen /period /slash
-/zero /one /two /three
-/four /five /six /seven
-/eight /nine /colon /semicolon
-/less /equal /greater /question
-/at /A /B /C
-/D /E /F /G
-/H /I /J /K
-/L /M /N /O
-/P /Q /R /S
-/T /U /V /W
-/X /Y /Z /bracketleft
-/backslash /bracketright /asciicircum /underscore
-/quoteleft /a /b /c
-/d /e /f /g
-/h /i /j /k
-/l /m /n /o
-/p /q /r /s
-/t /u /v /w
-/x /y /z /braceleft
-/bar /braceright /tilde /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/space /exclamdown /cent /sterling
-/currency /yen /brokenbar /section
-/dieresis /copyright /ordfeminine /guillemotleft
-/logicalnot /hyphen /registered /macron
-/degree /plusminus /twosuperior /threesuperior
-/acute /mu /paragraph /bullet
-/cedilla /onesuperior /ordmasculine /guillemotright
-/onequarter /onehalf /threequarters /questiondown
-/Agrave /Aacute /Acircumflex /Atilde
-/Adieresis /Aring /AE /Ccedilla
-/Egrave /Eacute /Ecircumflex /Edieresis
-/Igrave /Iacute /Icircumflex /Idieresis
-/Eth /Ntilde /Ograve /Oacute
-/Ocircumflex /Otilde /Odieresis /multiply
-/Oslash /Ugrave /Uacute /Ucircumflex
-/Udieresis /Yacute /Thorn /germandbls
-/agrave /aacute /acircumflex /atilde
-/adieresis /aring /ae /ccedilla
-/egrave /eacute /ecircumflex /edieresis
-/igrave /iacute /icircumflex /idieresis
-/eth /ntilde /ograve /oacute
-/ocircumflex /otilde /odieresis /divide
-/oslash /ugrave /uacute /ucircumflex
-/udieresis /yacute /thorn /ydieresis
-] def
-%%EndResource
-%%EndProlog
-%%BeginSetup
-%%IncludeResource: font Courier-Bold
-%%IncludeResource: font Courier
-/HFpt_w 10 def
-/HFpt_h 10 def
-/Courier-Bold /HF-gs-font MF
-/HF /HF-gs-font findfont [HFpt_w 0 0 HFpt_h 0 0] makefont def
-/Courier /F-gs-font MF
-/F-gs-font 10 10 SF
-/#copies 1 def
-/d_page_w 520 def
-/d_page_h 747 def
-/d_header_x 0 def
-/d_header_y 747 def
-/d_header_w 520 def
-/d_header_h 0 def
-/d_footer_x 0 def
-/d_footer_y 0 def
-/d_footer_w 520 def
-/d_footer_h 0 def
-/d_output_w 520 def
-/d_output_h 747 def
-/cols 1 def
-userdict/PStoPSxform PStoPSmatrix matrix currentmatrix
- matrix invertmatrix matrix concatmatrix
- matrix invertmatrix put
-%%EndSetup
-%%Page: (0,1) 1
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 1 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 701 M
-(Network Working Group T. Ylonen) s
-5 690 M
-(Internet-Draft SSH Communications Security Corp) s
-5 679 M
-(Expires: March 31, 2004 D. Moffat, Editor, Ed.) s
-5 668 M
-( Sun Microsystems, Inc) s
-5 657 M
-( Oct 2003) s
-5 624 M
-( SSH Transport Layer Protocol) s
-5 613 M
-( draft-ietf-secsh-transport-17.txt) s
-5 591 M
-(Status of this Memo) s
-5 569 M
-( This document is an Internet-Draft and is in full conformance with) s
-5 558 M
-( all provisions of Section 10 of RFC2026.) s
-5 536 M
-( Internet-Drafts are working documents of the Internet Engineering) s
-5 525 M
-( Task Force \(IETF\), its areas, and its working groups. Note that other) s
-5 514 M
-( groups may also distribute working documents as Internet-Drafts.) s
-5 492 M
-( Internet-Drafts are draft documents valid for a maximum of six months) s
-5 481 M
-( and may be updated, replaced, or obsoleted by other documents at any) s
-5 470 M
-( time. It is inappropriate to use Internet-Drafts as reference) s
-5 459 M
-( material or to cite them other than as "work in progress.") s
-5 437 M
-( The list of current Internet-Drafts can be accessed at http://) s
-5 426 M
-( www.ietf.org/ietf/1id-abstracts.txt.) s
-5 404 M
-( The list of Internet-Draft Shadow Directories can be accessed at) s
-5 393 M
-( http://www.ietf.org/shadow.html.) s
-5 371 M
-( This Internet-Draft will expire on March 31, 2004.) s
-5 349 M
-(Copyright Notice) s
-5 327 M
-( Copyright \(C\) The Internet Society \(2003\). All Rights Reserved.) s
-5 305 M
-(Abstract) s
-5 283 M
-( SSH is a protocol for secure remote login and other secure network) s
-5 272 M
-( services over an insecure network.) s
-5 250 M
-( This document describes the SSH transport layer protocol which) s
-5 239 M
-( typically runs on top of TCP/IP. The protocol can be used as a basis) s
-5 228 M
-( for a number of secure network services. It provides strong) s
-5 217 M
-( encryption, server authentication, and integrity protection. It may) s
-5 206 M
-( also provide compression.) s
-5 184 M
-( Key exchange method, public key algorithm, symmetric encryption) s
-5 173 M
-( algorithm, message authentication algorithm, and hash algorithm are) s
-5 129 M
-(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 1]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 2 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Transport Layer Protocol Oct 2003) s
-5 690 M
-( all negotiated.) s
-5 668 M
-( This document also describes the Diffie-Hellman key exchange method) s
-5 657 M
-( and the minimal set of algorithms that are needed to implement the) s
-5 646 M
-( SSH transport layer protocol.) s
-5 624 M
-(Table of Contents) s
-5 602 M
-( 1. Contributors . . . . . . . . . . . . . . . . . . . . . . . . 3) s
-5 591 M
-( 2. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3) s
-5 580 M
-( 3. Conventions Used in This Document . . . . . . . . . . . . . 3) s
-5 569 M
-( 4. Connection Setup . . . . . . . . . . . . . . . . . . . . . . 3) s
-5 558 M
-( 4.1 Use over TCP/IP . . . . . . . . . . . . . . . . . . . . . . 4) s
-5 547 M
-( 4.2 Protocol Version Exchange . . . . . . . . . . . . . . . . . 4) s
-5 536 M
-( 4.3 Compatibility With Old SSH Versions . . . . . . . . . . . . 4) s
-5 525 M
-( 4.3.1 Old Client, New Server . . . . . . . . . . . . . . . . . . . 5) s
-5 514 M
-( 4.3.2 New Client, Old Server . . . . . . . . . . . . . . . . . . . 5) s
-5 503 M
-( 5. Binary Packet Protocol . . . . . . . . . . . . . . . . . . . 5) s
-5 492 M
-( 5.1 Maximum Packet Length . . . . . . . . . . . . . . . . . . . 6) s
-5 481 M
-( 5.2 Compression . . . . . . . . . . . . . . . . . . . . . . . . 7) s
-5 470 M
-( 5.3 Encryption . . . . . . . . . . . . . . . . . . . . . . . . . 7) s
-5 459 M
-( 5.4 Data Integrity . . . . . . . . . . . . . . . . . . . . . . . 9) s
-5 448 M
-( 5.5 Key Exchange Methods . . . . . . . . . . . . . . . . . . . . 10) s
-5 437 M
-( 5.6 Public Key Algorithms . . . . . . . . . . . . . . . . . . . 11) s
-5 426 M
-( 6. Key Exchange . . . . . . . . . . . . . . . . . . . . . . . . 13) s
-5 415 M
-( 6.1 Algorithm Negotiation . . . . . . . . . . . . . . . . . . . 13) s
-5 404 M
-( 6.2 Output from Key Exchange . . . . . . . . . . . . . . . . . . 16) s
-5 393 M
-( 6.3 Taking Keys Into Use . . . . . . . . . . . . . . . . . . . . 17) s
-5 382 M
-( 7. Diffie-Hellman Key Exchange . . . . . . . . . . . . . . . . 18) s
-5 371 M
-( 7.1 diffie-hellman-group1-sha1 . . . . . . . . . . . . . . . . . 19) s
-5 360 M
-( 8. Key Re-Exchange . . . . . . . . . . . . . . . . . . . . . . 20) s
-5 349 M
-( 9. Service Request . . . . . . . . . . . . . . . . . . . . . . 21) s
-5 338 M
-( 10. Additional Messages . . . . . . . . . . . . . . . . . . . . 21) s
-5 327 M
-( 10.1 Disconnection Message . . . . . . . . . . . . . . . . . . . 22) s
-5 316 M
-( 10.2 Ignored Data Message . . . . . . . . . . . . . . . . . . . . 22) s
-5 305 M
-( 10.3 Debug Message . . . . . . . . . . . . . . . . . . . . . . . 23) s
-5 294 M
-( 10.4 Reserved Messages . . . . . . . . . . . . . . . . . . . . . 23) s
-5 283 M
-( 11. Summary of Message Numbers . . . . . . . . . . . . . . . . . 23) s
-5 272 M
-( 12. IANA Considerations . . . . . . . . . . . . . . . . . . . . 24) s
-5 261 M
-( 13. Security Considerations . . . . . . . . . . . . . . . . . . 24) s
-5 250 M
-( 14. Intellectual Property . . . . . . . . . . . . . . . . . . . 24) s
-5 239 M
-( 15. Additional Information . . . . . . . . . . . . . . . . . . . 24) s
-5 228 M
-( Authors' Addresses . . . . . . . . . . . . . . . . . . . . . 26) s
-5 217 M
-( Normative . . . . . . . . . . . . . . . . . . . . . . . . . 25) s
-5 206 M
-( Informative . . . . . . . . . . . . . . . . . . . . . . . . 25) s
-5 195 M
-( A. Contibutors . . . . . . . . . . . . . . . . . . . . . . . . 27) s
-5 184 M
-( Intellectual Property and Copyright Statements . . . . . . . 28) s
-5 129 M
-(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 2]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (2,3) 2
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 3 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Transport Layer Protocol Oct 2003) s
-5 690 M
-(1. Contributors) s
-5 668 M
-( The major original contributors of this document were: Tatu Ylonen,) s
-5 657 M
-( Tero Kivinen, Timo J. Rinne, Sami Lehtinen \(all of SSH Communications) s
-5 646 M
-( Security Corp\), and Markku-Juhani O. Saarinen \(University of) s
-5 635 M
-( Jyvaskyla\)) s
-5 613 M
-( The document editor is: [email protected]. Comments on this) s
-5 602 M
-( internet draft should be sent to the IETF SECSH working group,) s
-5 591 M
-( details at: http://ietf.org/html.charters/secsh-charter.html) s
-5 569 M
-(2. Introduction) s
-5 547 M
-( The SSH transport layer is a secure low level transport protocol. It) s
-5 536 M
-( provides strong encryption, cryptographic host authentication, and) s
-5 525 M
-( integrity protection.) s
-5 503 M
-( Authentication in this protocol level is host-based; this protocol) s
-5 492 M
-( does not perform user authentication. A higher level protocol for) s
-5 481 M
-( user authentication can be designed on top of this protocol.) s
-5 459 M
-( The protocol has been designed to be simple, flexible, to allow) s
-5 448 M
-( parameter negotiation, and to minimize the number of round-trips.) s
-5 437 M
-( Key exchange method, public key algorithm, symmetric encryption) s
-5 426 M
-( algorithm, message authentication algorithm, and hash algorithm are) s
-5 415 M
-( all negotiated. It is expected that in most environments, only 2) s
-5 404 M
-( round-trips will be needed for full key exchange, server) s
-5 393 M
-( authentication, service request, and acceptance notification of) s
-5 382 M
-( service request. The worst case is 3 round-trips.) s
-5 360 M
-(3. Conventions Used in This Document) s
-5 338 M
-( The keywords "MUST", "MUST NOT", "REQUIRED", "SHOULD", "SHOULD NOT",) s
-5 327 M
-( and "MAY" that appear in this document are to be interpreted as) s
-5 316 M
-( described in [RFC2119].) s
-5 294 M
-( The used data types and terminology are specified in the architecture) s
-5 283 M
-( document [SSH-ARCH].) s
-5 261 M
-( The architecture document also discusses the algorithm naming) s
-5 250 M
-( conventions that MUST be used with the SSH protocols.) s
-5 228 M
-(4. Connection Setup) s
-5 206 M
-( SSH works over any 8-bit clean, binary-transparent transport. The) s
-5 195 M
-( underlying transport SHOULD protect against transmission errors as) s
-5 184 M
-( such errors cause the SSH connection to terminate.) s
-5 129 M
-(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 3]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 4 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Transport Layer Protocol Oct 2003) s
-5 690 M
-( The client initiates the connection.) s
-5 668 M
-(4.1 Use over TCP/IP) s
-5 646 M
-( When used over TCP/IP, the server normally listens for connections on) s
-5 635 M
-( port 22. This port number has been registered with the IANA, and has) s
-5 624 M
-( been officially assigned for SSH.) s
-5 602 M
-(4.2 Protocol Version Exchange) s
-5 580 M
-( When the connection has been established, both sides MUST send an) s
-5 569 M
-( identification string of the form "SSH-protoversion-softwareversion) s
-5 558 M
-( comments", followed by carriage return and newline characters \(ASCII) s
-5 547 M
-( 13 and 10, respectively\). Both sides MUST be able to process) s
-5 536 M
-( identification strings without carriage return character. No null) s
-5 525 M
-( character is sent. The maximum length of the string is 255) s
-5 514 M
-( characters, including the carriage return and newline.) s
-5 492 M
-( The part of the identification string preceding carriage return and) s
-5 481 M
-( newline is used in the Diffie-Hellman key exchange \(see Section) s
-5 470 M
-( Section 7\).) s
-5 448 M
-( The server MAY send other lines of data before sending the version) s
-5 437 M
-( string. Each line SHOULD be terminated by a carriage return and) s
-5 426 M
-( newline. Such lines MUST NOT begin with "SSH-", and SHOULD be) s
-5 415 M
-( encoded in ISO-10646 UTF-8 [RFC2279] \(language is not specified\).) s
-5 404 M
-( Clients MUST be able to process such lines; they MAY be silently) s
-5 393 M
-( ignored, or MAY be displayed to the client user; if they are) s
-5 382 M
-( displayed, control character filtering discussed in [SSH-ARCH] SHOULD) s
-5 371 M
-( be used. The primary use of this feature is to allow TCP-wrappers to) s
-5 360 M
-( display an error message before disconnecting.) s
-5 338 M
-( Version strings MUST consist of printable US-ASCII characters, not) s
-5 327 M
-( including whitespaces or a minus sign \(-\). The version string is) s
-5 316 M
-( primarily used to trigger compatibility extensions and to indicate) s
-5 305 M
-( the capabilities of an implementation. The comment string should) s
-5 294 M
-( contain additional information that might be useful in solving user) s
-5 283 M
-( problems.) s
-5 261 M
-( The protocol version described in this document is 2.0.) s
-5 239 M
-( Key exchange will begin immediately after sending this identifier.) s
-5 228 M
-( All packets following the identification string SHALL use the binary) s
-5 217 M
-( packet protocol, to be described below.) s
-5 195 M
-(4.3 Compatibility With Old SSH Versions) s
-5 173 M
-( During the transition period, it is important to be able to work in a) s
-5 129 M
-(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 4]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (4,5) 3
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 5 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Transport Layer Protocol Oct 2003) s
-5 690 M
-( way that is compatible with the installed SSH clients and servers) s
-5 679 M
-( that use an older version of the protocol. Information in this) s
-5 668 M
-( section is only relevant for implementations supporting compatibility) s
-5 657 M
-( with SSH versions 1.x. There is no standards track or informational) s
-5 646 M
-( draft available that defines the SSH 1.x protocol. The only known) s
-5 635 M
-( documentation of the 1.x protocol is contained in README files that) s
-5 624 M
-( are shipped along with the source code.) s
-5 602 M
-(4.3.1 Old Client, New Server) s
-5 580 M
-( Server implementations MAY support a configurable "compatibility") s
-5 569 M
-( flag that enables compatibility with old versions. When this flag is) s
-5 558 M
-( on, the server SHOULD identify its protocol version as "1.99".) s
-5 547 M
-( Clients using protocol 2.0 MUST be able to identify this as identical) s
-5 536 M
-( to "2.0". In this mode the server SHOULD NOT send the carriage) s
-5 525 M
-( return character \(ASCII 13\) after the version identification string.) s
-5 503 M
-( In the compatibility mode the server SHOULD NOT send any further data) s
-5 492 M
-( after its initialization string until it has received an) s
-5 481 M
-( identification string from the client. The server can then determine) s
-5 470 M
-( whether the client is using an old protocol, and can revert to the) s
-5 459 M
-( old protocol if required. In the compatibility mode, the server MUST) s
-5 448 M
-( NOT send additional data before the version string.) s
-5 426 M
-( When compatibility with old clients is not needed, the server MAY) s
-5 415 M
-( send its initial key exchange data immediately after the) s
-5 404 M
-( identification string.) s
-5 382 M
-(4.3.2 New Client, Old Server) s
-5 360 M
-( Since the new client MAY immediately send additional data after its) s
-5 349 M
-( identification string \(before receiving server's identification\), the) s
-5 338 M
-( old protocol may already have been corrupted when the client learns) s
-5 327 M
-( that the server is old. When this happens, the client SHOULD close) s
-5 316 M
-( the connection to the server, and reconnect using the old protocol.) s
-5 294 M
-(5. Binary Packet Protocol) s
-5 272 M
-( Each packet is in the following format:) s
-5 250 M
-( uint32 packet_length) s
-5 239 M
-( byte padding_length) s
-5 228 M
-( byte[n1] payload; n1 = packet_length - padding_length - 1) s
-5 217 M
-( byte[n2] random padding; n2 = padding_length) s
-5 206 M
-( byte[m] mac \(message authentication code\); m = mac_length) s
-5 184 M
-( packet_length) s
-5 129 M
-(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 5]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 6 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Transport Layer Protocol Oct 2003) s
-5 690 M
-( The length of the packet \(bytes\), not including MAC or the) s
-5 679 M
-( packet_length field itself.) s
-5 657 M
-( padding_length) s
-5 646 M
-( Length of padding \(bytes\).) s
-5 624 M
-( payload) s
-5 613 M
-( The useful contents of the packet. If compression has been) s
-5 602 M
-( negotiated, this field is compressed. Initially, compression) s
-5 591 M
-( MUST be "none".) s
-5 569 M
-( random padding) s
-5 558 M
-( Arbitrary-length padding, such that the total length of) s
-5 547 M
-( \(packet_length || padding_length || payload || padding\) is a) s
-5 536 M
-( multiple of the cipher block size or 8, whichever is larger.) s
-5 525 M
-( There MUST be at least four bytes of padding. The padding) s
-5 514 M
-( SHOULD consist of random bytes. The maximum amount of padding) s
-5 503 M
-( is 255 bytes.) s
-5 481 M
-( mac) s
-5 470 M
-( Message authentication code. If message authentication has) s
-5 459 M
-( been negotiated, this field contains the MAC bytes. Initially,) s
-5 448 M
-( the MAC algorithm MUST be "none".) s
-5 415 M
-( Note that length of the concatenation of packet length, padding) s
-5 404 M
-( length, payload, and padding MUST be a multiple of the cipher block) s
-5 393 M
-( size or 8, whichever is larger. This constraint MUST be enforced) s
-5 382 M
-( even when using stream ciphers. Note that the packet length field is) s
-5 371 M
-( also encrypted, and processing it requires special care when sending) s
-5 360 M
-( or receiving packets.) s
-5 338 M
-( The minimum size of a packet is 16 \(or the cipher block size,) s
-5 327 M
-( whichever is larger\) bytes \(plus MAC\); implementations SHOULD decrypt) s
-5 316 M
-( the length after receiving the first 8 \(or cipher block size,) s
-5 305 M
-( whichever is larger\) bytes of a packet.) s
-5 283 M
-(5.1 Maximum Packet Length) s
-5 261 M
-( All implementations MUST be able to process packets with uncompressed) s
-5 250 M
-( payload length of 32768 bytes or less and total packet size of 35000) s
-5 239 M
-( bytes or less \(including length, padding length, payload, padding,) s
-5 228 M
-( and MAC.\). The maximum of 35000 bytes is an arbitrary chosen value) s
-5 217 M
-( larger than uncompressed size. Implementations SHOULD support longer) s
-5 206 M
-( packets, where they might be needed, e.g. if an implementation wants) s
-5 195 M
-( to send a very large number of certificates. Such packets MAY be) s
-5 184 M
-( sent if the version string indicates that the other party is able to) s
-5 173 M
-( process them. However, implementations SHOULD check that the packet) s
-5 129 M
-(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 6]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (6,7) 4
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 7 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Transport Layer Protocol Oct 2003) s
-5 690 M
-( length is reasonable for the implementation to avoid) s
-5 679 M
-( denial-of-service and/or buffer overflow attacks.) s
-5 657 M
-(5.2 Compression) s
-5 635 M
-( If compression has been negotiated, the payload field \(and only it\)) s
-5 624 M
-( will be compressed using the negotiated algorithm. The length field) s
-5 613 M
-( and MAC will be computed from the compressed payload. Encryption will) s
-5 602 M
-( be done after compression.) s
-5 580 M
-( Compression MAY be stateful, depending on the method. Compression) s
-5 569 M
-( MUST be independent for each direction, and implementations MUST) s
-5 558 M
-( allow independently choosing the algorithm for each direction.) s
-5 536 M
-( The following compression methods are currently defined:) s
-5 514 M
-( none REQUIRED no compression) s
-5 503 M
-( zlib OPTIONAL ZLIB \(LZ77\) compression) s
-5 481 M
-( The "zlib" compression is described in [RFC1950] and in [RFC1951].) s
-5 470 M
-( The compression context is initialized after each key exchange, and) s
-5 459 M
-( is passed from one packet to the next with only a partial flush being) s
-5 448 M
-( performed at the end of each packet. A partial flush means that the) s
-5 437 M
-( current compressed block is ended and all data will be output. If the) s
-5 426 M
-( current block is not a stored block, one or more empty blocks are) s
-5 415 M
-( added after the current block to ensure that there are at least 8) s
-5 404 M
-( bits counting from the start of the end-of-block code of the current) s
-5 393 M
-( block to the end of the packet payload.) s
-5 371 M
-( Additional methods may be defined as specified in [SSH-ARCH].) s
-5 349 M
-(5.3 Encryption) s
-5 327 M
-( An encryption algorithm and a key will be negotiated during the key) s
-5 316 M
-( exchange. When encryption is in effect, the packet length, padding) s
-5 305 M
-( length, payload and padding fields of each packet MUST be encrypted) s
-5 294 M
-( with the given algorithm.) s
-5 272 M
-( The encrypted data in all packets sent in one direction SHOULD be) s
-5 261 M
-( considered a single data stream. For example, initialization vectors) s
-5 250 M
-( SHOULD be passed from the end of one packet to the beginning of the) s
-5 239 M
-( next packet. All ciphers SHOULD use keys with an effective key length) s
-5 228 M
-( of 128 bits or more.) s
-5 206 M
-( The ciphers in each direction MUST run independently of each other,) s
-5 195 M
-( and implementations MUST allow independently choosing the algorithm) s
-5 184 M
-( for each direction \(if multiple algorithms are allowed by local) s
-5 173 M
-( policy\).) s
-5 129 M
-(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 7]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 8 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Transport Layer Protocol Oct 2003) s
-5 690 M
-( The following ciphers are currently defined:) s
-5 668 M
-( 3des-cbc REQUIRED three-key 3DES in CBC mode) s
-5 657 M
-( blowfish-cbc OPTIONALi Blowfish in CBC mode) s
-5 646 M
-( twofish256-cbc OPTIONAL Twofish in CBC mode,) s
-5 635 M
-( with 256-bit key) s
-5 624 M
-( twofish-cbc OPTIONAL alias for "twofish256-cbc" \(this) s
-5 613 M
-( is being retained for) s
-5 602 M
-( historical reasons\)) s
-5 591 M
-( twofish192-cbc OPTIONAL Twofish with 192-bit key) s
-5 580 M
-( twofish128-cbc OPTIONAL Twofish with 128-bit key) s
-5 569 M
-( aes256-cbc OPTIONAL AES \(Rijndael\) in CBC mode,) s
-5 558 M
-( with 256-bit key) s
-5 547 M
-( aes192-cbc OPTIONAL AES with 192-bit key) s
-5 536 M
-( aes128-cbc RECOMMENDED AES with 128-bit key) s
-5 525 M
-( serpent256-cbc OPTIONAL Serpent in CBC mode, with) s
-5 514 M
-( 256-bit key) s
-5 503 M
-( serpent192-cbc OPTIONAL Serpent with 192-bit key) s
-5 492 M
-( serpent128-cbc OPTIONAL Serpent with 128-bit key) s
-5 481 M
-( arcfour OPTIONAL the ARCFOUR stream cipher) s
-5 470 M
-( idea-cbc OPTIONAL IDEA in CBC mode) s
-5 459 M
-( cast128-cbc OPTIONAL CAST-128 in CBC mode) s
-5 448 M
-( none OPTIONAL no encryption; NOT RECOMMENDED) s
-5 426 M
-( The "3des-cbc" cipher is three-key triple-DES) s
-5 415 M
-( \(encrypt-decrypt-encrypt\), where the first 8 bytes of the key are) s
-5 404 M
-( used for the first encryption, the next 8 bytes for the decryption,) s
-5 393 M
-( and the following 8 bytes for the final encryption. This requires 24) s
-5 382 M
-( bytes of key data \(of which 168 bits are actually used\). To) s
-5 371 M
-( implement CBC mode, outer chaining MUST be used \(i.e., there is only) s
-5 360 M
-( one initialization vector\). This is a block cipher with 8 byte) s
-5 349 M
-( blocks. This algorithm is defined in [FIPS-46-3]) s
-5 327 M
-( The "blowfish-cbc" cipher is Blowfish in CBC mode, with 128 bit keys) s
-5 316 M
-( [SCHNEIER]. This is a block cipher with 8 byte blocks.) s
-5 294 M
-( The "twofish-cbc" or "twofish256-cbc" cipher is Twofish in CBC mode,) s
-5 283 M
-( with 256 bit keys as described [TWOFISH]. This is a block cipher with) s
-5 272 M
-( 16 byte blocks.) s
-5 250 M
-( The "twofish192-cbc" cipher. Same as above but with 192-bit key.) s
-5 228 M
-( The "twofish128-cbc" cipher. Same as above but with 128-bit key.) s
-5 206 M
-( The "aes256-cbc" cipher is AES \(Advanced Encryption Standard\)) s
-5 195 M
-( [FIPS-197], formerly Rijndael, in CBC mode. This version uses 256-bit) s
-5 184 M
-( key.) s
-5 129 M
-(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 8]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (8,9) 5
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 9 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Transport Layer Protocol Oct 2003) s
-5 690 M
-( The "aes192-cbc" cipher. Same as above but with 192-bit key.) s
-5 668 M
-( The "aes128-cbc" cipher. Same as above but with 128-bit key.) s
-5 646 M
-( The "serpent256-cbc" cipher in CBC mode, with 256-bit key as) s
-5 635 M
-( described in the Serpent AES submission.) s
-5 613 M
-( The "serpent192-cbc" cipher. Same as above but with 192-bit key.) s
-5 591 M
-( The "serpent128-cbc" cipher. Same as above but with 128-bit key.) s
-5 569 M
-( The "arcfour" is the Arcfour stream cipher with 128 bit keys. The) s
-5 558 M
-( Arcfour cipher is believed to be compatible with the RC4 cipher) s
-5 547 M
-( [SCHNEIER]. RC4 is a registered trademark of RSA Data Security Inc.) s
-5 536 M
-( Arcfour \(and RC4\) has problems with weak keys, and should be used) s
-5 525 M
-( with caution.) s
-5 503 M
-( The "idea-cbc" cipher is the IDEA cipher in CBC mode [SCHNEIER].) s
-5 481 M
-( The "cast128-cbc" cipher is the CAST-128 cipher in CBC mode) s
-5 470 M
-( [RFC2144].) s
-5 448 M
-( The "none" algorithm specifies that no encryption is to be done.) s
-5 437 M
-( Note that this method provides no confidentiality protection, and it) s
-5 426 M
-( is not recommended. Some functionality \(e.g. password) s
-5 415 M
-( authentication\) may be disabled for security reasons if this cipher) s
-5 404 M
-( is chosen.) s
-5 382 M
-( Additional methods may be defined as specified in [SSH-ARCH].) s
-5 360 M
-(5.4 Data Integrity) s
-5 338 M
-( Data integrity is protected by including with each packet a message) s
-5 327 M
-( authentication code \(MAC\) that is computed from a shared secret,) s
-5 316 M
-( packet sequence number, and the contents of the packet.) s
-5 294 M
-( The message authentication algorithm and key are negotiated during) s
-5 283 M
-( key exchange. Initially, no MAC will be in effect, and its length) s
-5 272 M
-( MUST be zero. After key exchange, the selected MAC will be computed) s
-5 261 M
-( before encryption from the concatenation of packet data:) s
-5 239 M
-( mac = MAC\(key, sequence_number || unencrypted_packet\)) s
-5 217 M
-( where unencrypted_packet is the entire packet without MAC \(the length) s
-5 206 M
-( fields, payload and padding\), and sequence_number is an implicit) s
-5 195 M
-( packet sequence number represented as uint32. The sequence number is) s
-5 184 M
-( initialized to zero for the first packet, and is incremented after) s
-5 173 M
-( every packet \(regardless of whether encryption or MAC is in use\). It) s
-5 129 M
-(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 9]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 10 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Transport Layer Protocol Oct 2003) s
-5 690 M
-( is never reset, even if keys/algorithms are renegotiated later. It) s
-5 679 M
-( wraps around to zero after every 2^32 packets. The packet sequence) s
-5 668 M
-( number itself is not included in the packet sent over the wire.) s
-5 646 M
-( The MAC algorithms for each direction MUST run independently, and) s
-5 635 M
-( implementations MUST allow choosing the algorithm independently for) s
-5 624 M
-( both directions.) s
-5 602 M
-( The MAC bytes resulting from the MAC algorithm MUST be transmitted) s
-5 591 M
-( without encryption as the last part of the packet. The number of MAC) s
-5 580 M
-( bytes depends on the algorithm chosen.) s
-5 558 M
-( The following MAC algorithms are currently defined:) s
-5 536 M
-( hmac-sha1 REQUIRED HMAC-SHA1 \(digest length = key) s
-5 525 M
-( length = 20\)) s
-5 514 M
-( hmac-sha1-96 RECOMMENDED first 96 bits of HMAC-SHA1 \(digest) s
-5 503 M
-( length = 12, key length = 20\)) s
-5 492 M
-( hmac-md5 OPTIONAL HMAC-MD5 \(digest length = key) s
-5 481 M
-( length = 16\)) s
-5 470 M
-( hmac-md5-96 OPTIONAL first 96 bits of HMAC-MD5 \(digest) s
-5 459 M
-( length = 12, key length = 16\)) s
-5 448 M
-( none OPTIONAL no MAC; NOT RECOMMENDED) s
-5 426 M
-( Figure 1) s
-5 404 M
-( The "hmac-*" algorithms are described in [RFC2104] The "*-n" MACs use) s
-5 393 M
-( only the first n bits of the resulting value.) s
-5 371 M
-( The hash algorithms are described in [SCHNEIER].) s
-5 349 M
-( Additional methods may be defined as specified in [SSH-ARCH].) s
-5 327 M
-(5.5 Key Exchange Methods) s
-5 305 M
-( The key exchange method specifies how one-time session keys are) s
-5 294 M
-( generated for encryption and for authentication, and how the server) s
-5 283 M
-( authentication is done.) s
-5 261 M
-( Only one REQUIRED key exchange method has been defined:) s
-5 239 M
-( diffie-hellman-group1-sha1 REQUIRED) s
-5 217 M
-( This method is described later in this document.) s
-5 195 M
-( Additional methods may be defined as specified in [SSH-ARCH].) s
-5 129 M
-(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 10]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (10,11) 6
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 11 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Transport Layer Protocol Oct 2003) s
-5 690 M
-(5.6 Public Key Algorithms) s
-5 668 M
-( This protocol has been designed to be able to operate with almost any) s
-5 657 M
-( public key format, encoding, and algorithm \(signature and/or) s
-5 646 M
-( encryption\).) s
-5 624 M
-( There are several aspects that define a public key type:) s
-5 613 M
-( o Key format: how is the key encoded and how are certificates) s
-5 602 M
-( represented. The key blobs in this protocol MAY contain) s
-5 591 M
-( certificates in addition to keys.) s
-5 580 M
-( o Signature and/or encryption algorithms. Some key types may not) s
-5 569 M
-( support both signing and encryption. Key usage may also be) s
-5 558 M
-( restricted by policy statements in e.g. certificates. In this) s
-5 547 M
-( case, different key types SHOULD be defined for the different) s
-5 536 M
-( policy alternatives.) s
-5 525 M
-( o Encoding of signatures and/or encrypted data. This includes but is) s
-5 514 M
-( not limited to padding, byte order, and data formats.) s
-5 492 M
-( The following public key and/or certificate formats are currently defined:) s
-5 470 M
-( ssh-dss REQUIRED sign Raw DSS Key) s
-5 459 M
-( ssh-rsa RECOMMENDED sign Raw RSA Key) s
-5 448 M
-( x509v3-sign-rsa OPTIONAL sign X.509 certificates \(RSA key\)) s
-5 437 M
-( x509v3-sign-dss OPTIONAL sign X.509 certificates \(DSS key\)) s
-5 426 M
-( spki-sign-rsa OPTIONAL sign SPKI certificates \(RSA key\)) s
-5 415 M
-( spki-sign-dss OPTIONAL sign SPKI certificates \(DSS key\)) s
-5 404 M
-( pgp-sign-rsa OPTIONAL sign OpenPGP certificates \(RSA key\)) s
-5 393 M
-( pgp-sign-dss OPTIONAL sign OpenPGP certificates \(DSS key\)) s
-5 371 M
-( Additional key types may be defined as specified in [SSH-ARCH].) s
-5 349 M
-( The key type MUST always be explicitly known \(from algorithm) s
-5 338 M
-( negotiation or some other source\). It is not normally included in) s
-5 327 M
-( the key blob.) s
-5 305 M
-( Certificates and public keys are encoded as follows:) s
-5 283 M
-( string certificate or public key format identifier) s
-5 272 M
-( byte[n] key/certificate data) s
-5 250 M
-( The certificate part may have be a zero length string, but a public) s
-5 239 M
-( key is required. This is the public key that will be used for) s
-5 228 M
-( authentication; the certificate sequence contained in the certificate) s
-5 217 M
-( blob can be used to provide authorization.) s
-5 195 M
-( Public key / certifcate formats that do not explicitly specify a) s
-5 184 M
-( signature format identifier MUST use the public key / certificate) s
-5 173 M
-( format identifier as the signature identifier.) s
-5 129 M
-(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 11]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 12 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Transport Layer Protocol Oct 2003) s
-5 690 M
-( Signatures are encoded as follows:) s
-5 679 M
-( string signature format identifier \(as specified by the) s
-5 668 M
-( public key / cert format\)) s
-5 657 M
-( byte[n] signature blob in format specific encoding.) s
-5 624 M
-( The "ssh-dss" key format has the following specific encoding:) s
-5 602 M
-( string "ssh-dss") s
-5 591 M
-( mpint p) s
-5 580 M
-( mpint q) s
-5 569 M
-( mpint g) s
-5 558 M
-( mpint y) s
-5 536 M
-( Here the p, q, g, and y parameters form the signature key blob.) s
-5 514 M
-( Signing and verifying using this key format is done according to the) s
-5 503 M
-( Digital Signature Standard [FIPS-186] using the SHA-1 hash. A) s
-5 492 M
-( description can also be found in [SCHNEIER].) s
-5 470 M
-( The resulting signature is encoded as follows:) s
-5 448 M
-( string "ssh-dss") s
-5 437 M
-( string dss_signature_blob) s
-5 415 M
-( dss_signature_blob is encoded as a string containing r followed by s) s
-5 404 M
-( \(which are 160 bits long integers, without lengths or padding,) s
-5 393 M
-( unsigned and in network byte order\).) s
-5 371 M
-( The "ssh-rsa" key format has the following specific encoding:) s
-5 349 M
-( string "ssh-rsa") s
-5 338 M
-( mpint e) s
-5 327 M
-( mpint n) s
-5 305 M
-( Here the e and n parameters form the signature key blob.) s
-5 283 M
-( Signing and verifying using this key format is done according to) s
-5 272 M
-( [SCHNEIER] and [PKCS1] using the SHA-1 hash.) s
-5 250 M
-( The resulting signature is encoded as follows:) s
-5 228 M
-( string "ssh-rsa") s
-5 217 M
-( string rsa_signature_blob) s
-5 195 M
-( rsa_signature_blob is encoded as a string containing s \(which is an) s
-5 184 M
-( integer, without lengths or padding, unsigned and in network byte) s
-5 173 M
-( order\).) s
-5 129 M
-(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 12]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (12,13) 7
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 13 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Transport Layer Protocol Oct 2003) s
-5 690 M
-( The "spki-sign-rsa" method indicates that the certificate blob) s
-5 679 M
-( contains a sequence of SPKI certificates. The format of SPKI) s
-5 668 M
-( certificates is described in [RFC2693]. This method indicates that) s
-5 657 M
-( the key \(or one of the keys in the certificate\) is an RSA-key.) s
-5 635 M
-( The "spki-sign-dss". As above, but indicates that the key \(or one of) s
-5 624 M
-( the keys in the certificate\) is a DSS-key.) s
-5 602 M
-( The "pgp-sign-rsa" method indicates the certificates, the public key,) s
-5 591 M
-( and the signature are in OpenPGP compatible binary format) s
-5 580 M
-( \([RFC2440]\). This method indicates that the key is an RSA-key.) s
-5 558 M
-( The "pgp-sign-dss". As above, but indicates that the key is a) s
-5 547 M
-( DSS-key.) s
-5 525 M
-(6. Key Exchange) s
-5 503 M
-( Key exchange begins by each side sending lists of supported) s
-5 492 M
-( algorithms. Each side has a preferred algorithm in each category, and) s
-5 481 M
-( it is assumed that most implementations at any given time will use) s
-5 470 M
-( the same preferred algorithm. Each side MAY guess which algorithm) s
-5 459 M
-( the other side is using, and MAY send an initial key exchange packet) s
-5 448 M
-( according to the algorithm if appropriate for the preferred method.) s
-5 426 M
-( Guess is considered wrong, if:) s
-5 415 M
-( o the kex algorithm and/or the host key algorithm is guessed wrong) s
-5 404 M
-( \(server and client have different preferred algorithm\), or) s
-5 393 M
-( o if any of the other algorithms cannot be agreed upon \(the) s
-5 382 M
-( procedure is defined below in Section Section 6.1\).) s
-5 360 M
-( Otherwise, the guess is considered to be right and the optimistically) s
-5 349 M
-( sent packet MUST be handled as the first key exchange packet.) s
-5 327 M
-( However, if the guess was wrong, and a packet was optimistically sent) s
-5 316 M
-( by one or both parties, such packets MUST be ignored \(even if the) s
-5 305 M
-( error in the guess would not affect the contents of the initial) s
-5 294 M
-( packet\(s\)\), and the appropriate side MUST send the correct initial) s
-5 283 M
-( packet.) s
-5 261 M
-( Server authentication in the key exchange MAY be implicit. After a) s
-5 250 M
-( key exchange with implicit server authentication, the client MUST) s
-5 239 M
-( wait for response to its service request message before sending any) s
-5 228 M
-( further data.) s
-5 206 M
-(6.1 Algorithm Negotiation) s
-5 184 M
-( Key exchange begins by each side sending the following packet:) s
-5 129 M
-(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 13]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 14 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Transport Layer Protocol Oct 2003) s
-5 690 M
-( byte SSH_MSG_KEXINIT) s
-5 679 M
-( byte[16] cookie \(random bytes\)) s
-5 668 M
-( string kex_algorithms) s
-5 657 M
-( string server_host_key_algorithms) s
-5 646 M
-( string encryption_algorithms_client_to_server) s
-5 635 M
-( string encryption_algorithms_server_to_client) s
-5 624 M
-( string mac_algorithms_client_to_server) s
-5 613 M
-( string mac_algorithms_server_to_client) s
-5 602 M
-( string compression_algorithms_client_to_server) s
-5 591 M
-( string compression_algorithms_server_to_client) s
-5 580 M
-( string languages_client_to_server) s
-5 569 M
-( string languages_server_to_client) s
-5 558 M
-( boolean first_kex_packet_follows) s
-5 547 M
-( uint32 0 \(reserved for future extension\)) s
-5 525 M
-( Each of the algorithm strings MUST be a comma-separated list of) s
-5 514 M
-( algorithm names \(see ''Algorithm Naming'' in [SSH-ARCH]\). Each) s
-5 503 M
-( supported \(allowed\) algorithm MUST be listed in order of preference.) s
-5 481 M
-( The first algorithm in each list MUST be the preferred \(guessed\)) s
-5 470 M
-( algorithm. Each string MUST contain at least one algorithm name.) s
-5 437 M
-( cookie) s
-5 426 M
-( The cookie MUST be a random value generated by the sender. Its) s
-5 415 M
-( purpose is to make it impossible for either side to fully) s
-5 404 M
-( determine the keys and the session identifier.) s
-5 382 M
-( kex_algorithms) s
-5 371 M
-( Key exchange algorithms were defined above. The first) s
-5 360 M
-( algorithm MUST be the preferred \(and guessed\) algorithm. If) s
-5 349 M
-( both sides make the same guess, that algorithm MUST be used.) s
-5 338 M
-( Otherwise, the following algorithm MUST be used to choose a key) s
-5 327 M
-( exchange method: iterate over client's kex algorithms, one at a) s
-5 316 M
-( time. Choose the first algorithm that satisfies the following) s
-5 305 M
-( conditions:) s
-5 294 M
-( + the server also supports the algorithm,) s
-5 283 M
-( + if the algorithm requires an encryption-capable host key,) s
-5 272 M
-( there is an encryption-capable algorithm on the server's) s
-5 261 M
-( server_host_key_algorithms that is also supported by the) s
-5 250 M
-( client, and) s
-5 239 M
-( + if the algorithm requires a signature-capable host key,) s
-5 228 M
-( there is a signature-capable algorithm on the server's) s
-5 217 M
-( server_host_key_algorithms that is also supported by the) s
-5 206 M
-( client.) s
-5 195 M
-( + If no algorithm satisfying all these conditions can be) s
-5 184 M
-( found, the connection fails, and both sides MUST disconnect.) s
-5 129 M
-(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 14]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (14,15) 8
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 15 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Transport Layer Protocol Oct 2003) s
-5 690 M
-( server_host_key_algorithms) s
-5 679 M
-( List of the algorithms supported for the server host key. The) s
-5 668 M
-( server lists the algorithms for which it has host keys; the) s
-5 657 M
-( client lists the algorithms that it is willing to accept.) s
-5 646 M
-( \(There MAY be multiple host keys for a host, possibly with) s
-5 635 M
-( different algorithms.\)) s
-5 613 M
-( Some host keys may not support both signatures and encryption) s
-5 602 M
-( \(this can be determined from the algorithm\), and thus not all) s
-5 591 M
-( host keys are valid for all key exchange methods.) s
-5 569 M
-( Algorithm selection depends on whether the chosen key exchange) s
-5 558 M
-( algorithm requires a signature or encryption capable host key.) s
-5 547 M
-( It MUST be possible to determine this from the public key) s
-5 536 M
-( algorithm name. The first algorithm on the client's list that) s
-5 525 M
-( satisfies the requirements and is also supported by the server) s
-5 514 M
-( MUST be chosen. If there is no such algorithm, both sides MUST) s
-5 503 M
-( disconnect.) s
-5 481 M
-( encryption_algorithms) s
-5 470 M
-( Lists the acceptable symmetric encryption algorithms in order) s
-5 459 M
-( of preference. The chosen encryption algorithm to each) s
-5 448 M
-( direction MUST be the first algorithm on the client's list) s
-5 437 M
-( that is also on the server's list. If there is no such) s
-5 426 M
-( algorithm, both sides MUST disconnect.) s
-5 404 M
-( Note that "none" must be explicitly listed if it is to be) s
-5 393 M
-( acceptable. The defined algorithm names are listed in Section) s
-5 382 M
-( Section 5.3.) s
-5 360 M
-( mac_algorithms) s
-5 349 M
-( Lists the acceptable MAC algorithms in order of preference.) s
-5 338 M
-( The chosen MAC algorithm MUST be the first algorithm on the) s
-5 327 M
-( client's list that is also on the server's list. If there is) s
-5 316 M
-( no such algorithm, both sides MUST disconnect.) s
-5 294 M
-( Note that "none" must be explicitly listed if it is to be) s
-5 283 M
-( acceptable. The MAC algorithm names are listed in Section) s
-5 272 M
-( Figure 1.) s
-5 250 M
-( compression_algorithms) s
-5 239 M
-( Lists the acceptable compression algorithms in order of) s
-5 228 M
-( preference. The chosen compression algorithm MUST be the first) s
-5 217 M
-( algorithm on the client's list that is also on the server's) s
-5 206 M
-( list. If there is no such algorithm, both sides MUST) s
-5 195 M
-( disconnect.) s
-5 129 M
-(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 15]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 16 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Transport Layer Protocol Oct 2003) s
-5 690 M
-( Note that "none" must be explicitly listed if it is to be) s
-5 679 M
-( acceptable. The compression algorithm names are listed in) s
-5 668 M
-( Section Section 5.2.) s
-5 646 M
-( languages) s
-5 635 M
-( This is a comma-separated list of language tags in order of) s
-5 624 M
-( preference [RFC3066]. Both parties MAY ignore this list. If) s
-5 613 M
-( there are no language preferences, this list SHOULD be empty.) s
-5 602 M
-( Language tags SHOULD NOT be present unless they are known to be) s
-5 591 M
-( needed by the sending party.) s
-5 569 M
-( first_kex_packet_follows) s
-5 558 M
-( Indicates whether a guessed key exchange packet follows. If a) s
-5 547 M
-( guessed packet will be sent, this MUST be TRUE. If no guessed) s
-5 536 M
-( packet will be sent, this MUST be FALSE.) s
-5 514 M
-( After receiving the SSH_MSG_KEXINIT packet from the other side,) s
-5 503 M
-( each party will know whether their guess was right. If the) s
-5 492 M
-( other party's guess was wrong, and this field was TRUE, the) s
-5 481 M
-( next packet MUST be silently ignored, and both sides MUST then) s
-5 470 M
-( act as determined by the negotiated key exchange method. If) s
-5 459 M
-( the guess was right, key exchange MUST continue using the) s
-5 448 M
-( guessed packet.) s
-5 426 M
-( After the KEXINIT packet exchange, the key exchange algorithm is run.) s
-5 415 M
-( It may involve several packet exchanges, as specified by the key) s
-5 404 M
-( exchange method.) s
-5 382 M
-(6.2 Output from Key Exchange) s
-5 360 M
-( The key exchange produces two values: a shared secret K, and an) s
-5 349 M
-( exchange hash H. Encryption and authentication keys are derived from) s
-5 338 M
-( these. The exchange hash H from the first key exchange is) s
-5 327 M
-( additionally used as the session identifier, which is a unique) s
-5 316 M
-( identifier for this connection. It is used by authentication methods) s
-5 305 M
-( as a part of the data that is signed as a proof of possession of a) s
-5 294 M
-( private key. Once computed, the session identifier is not changed,) s
-5 283 M
-( even if keys are later re-exchanged.) s
-5 250 M
-( Each key exchange method specifies a hash function that is used in) s
-5 239 M
-( the key exchange. The same hash algorithm MUST be used in key) s
-5 228 M
-( derivation. Here, we'll call it HASH.) s
-5 195 M
-( Encryption keys MUST be computed as HASH of a known value and K as) s
-5 184 M
-( follows:) s
-5 129 M
-(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 16]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (16,17) 9
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 17 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Transport Layer Protocol Oct 2003) s
-5 690 M
-( o Initial IV client to server: HASH\(K || H || "A" || session_id\)) s
-5 679 M
-( \(Here K is encoded as mpint and "A" as byte and session_id as raw) s
-5 668 M
-( data."A" means the single character A, ASCII 65\).) s
-5 657 M
-( o Initial IV server to client: HASH\(K || H || "B" || session_id\)) s
-5 646 M
-( o Encryption key client to server: HASH\(K || H || "C" || session_id\)) s
-5 635 M
-( o Encryption key server to client: HASH\(K || H || "D" || session_id\)) s
-5 624 M
-( o Integrity key client to server: HASH\(K || H || "E" || session_id\)) s
-5 613 M
-( o Integrity key server to client: HASH\(K || H || "F" || session_id\)) s
-5 591 M
-( Key data MUST be taken from the beginning of the hash output. 128) s
-5 580 M
-( bits \(16 bytes\) MUST be used for algorithms with variable-length) s
-5 569 M
-( keys. The only variable key length algorithm defined in this document) s
-5 558 M
-( is arcfour\). For other algorithms, as many bytes as are needed are) s
-5 547 M
-( taken from the beginning of the hash value. If the key length needed) s
-5 536 M
-( is longer than the output of the HASH, the key is extended by) s
-5 525 M
-( computing HASH of the concatenation of K and H and the entire key so) s
-5 514 M
-( far, and appending the resulting bytes \(as many as HASH generates\) to) s
-5 503 M
-( the key. This process is repeated until enough key material is) s
-5 492 M
-( available; the key is taken from the beginning of this value. In) s
-5 481 M
-( other words:) s
-5 459 M
-( K1 = HASH\(K || H || X || session_id\) \(X is e.g. "A"\)) s
-5 448 M
-( K2 = HASH\(K || H || K1\)) s
-5 437 M
-( K3 = HASH\(K || H || K1 || K2\)) s
-5 426 M
-( ...) s
-5 415 M
-( key = K1 || K2 || K3 || ...) s
-5 393 M
-( This process will lose entropy if the amount of entropy in K is) s
-5 382 M
-( larger than the internal state size of HASH.) s
-5 360 M
-(6.3 Taking Keys Into Use) s
-5 338 M
-( Key exchange ends by each side sending an SSH_MSG_NEWKEYS message.) s
-5 327 M
-( This message is sent with the old keys and algorithms. All messages) s
-5 316 M
-( sent after this message MUST use the new keys and algorithms.) s
-5 283 M
-( When this message is received, the new keys and algorithms MUST be) s
-5 272 M
-( taken into use for receiving.) s
-5 239 M
-( This message is the only valid message after key exchange, in) s
-5 228 M
-( addition to SSH_MSG_DEBUG, SSH_MSG_DISCONNECT and SSH_MSG_IGNORE) s
-5 217 M
-( messages. The purpose of this message is to ensure that a party is) s
-5 206 M
-( able to respond with a disconnect message that the other party can) s
-5 195 M
-( understand if something goes wrong with the key exchange.) s
-5 184 M
-( Implementations MUST NOT accept any other messages after key exchange) s
-5 173 M
-( before receiving SSH_MSG_NEWKEYS.) s
-5 129 M
-(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 17]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 18 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Transport Layer Protocol Oct 2003) s
-5 690 M
-( byte SSH_MSG_NEWKEYS) s
-5 657 M
-(7. Diffie-Hellman Key Exchange) s
-5 635 M
-( The Diffie-Hellman key exchange provides a shared secret that can not) s
-5 624 M
-( be determined by either party alone. The key exchange is combined) s
-5 613 M
-( with a signature with the host key to provide host authentication.) s
-5 580 M
-( In the following description \(C is the client, S is the server; p is) s
-5 569 M
-( a large safe prime, g is a generator for a subgroup of GF\(p\), and q) s
-5 558 M
-( is the order of the subgroup; V_S is S's version string; V_C is C's) s
-5 547 M
-( version string; K_S is S's public host key; I_C is C's KEXINIT) s
-5 536 M
-( message and I_S S's KEXINIT message which have been exchanged before) s
-5 525 M
-( this part begins\):) s
-5 492 M
-( 1. C generates a random number x \(1 < x < q\) and computes e = g^x) s
-5 481 M
-( mod p. C sends "e" to S.) s
-5 459 M
-( 2. S generates a random number y \(0 < y < q\) and computes f = g^y) s
-5 448 M
-( mod p. S receives "e". It computes K = e^y mod p, H = hash\(V_C) s
-5 437 M
-( || V_S || I_C || I_S || K_S || e || f || K\) \(these elements are) s
-5 426 M
-( encoded according to their types; see below\), and signature s on) s
-5 415 M
-( H with its private host key. S sends "K_S || f || s" to C. The) s
-5 404 M
-( signing operation may involve a second hashing operation.) s
-5 382 M
-( 3. C verifies that K_S really is the host key for S \(e.g. using) s
-5 371 M
-( certificates or a local database\). C is also allowed to accept) s
-5 360 M
-( the key without verification; however, doing so will render the) s
-5 349 M
-( protocol insecure against active attacks \(but may be desirable) s
-5 338 M
-( for practical reasons in the short term in many environments\). C) s
-5 327 M
-( then computes K = f^x mod p, H = hash\(V_C || V_S || I_C || I_S ||) s
-5 316 M
-( K_S || e || f || K\), and verifies the signature s on H.) s
-5 294 M
-( Either side MUST NOT send or accept e or f values that are not in the) s
-5 283 M
-( range [1, p-1]. If this condition is violated, the key exchange) s
-5 272 M
-( fails.) s
-5 239 M
-( This is implemented with the following messages. The hash algorithm) s
-5 228 M
-( for computing the exchange hash is defined by the method name, and is) s
-5 217 M
-( called HASH. The public key algorithm for signing is negotiated with) s
-5 206 M
-( the KEXINIT messages.) s
-5 184 M
-( First, the client sends the following:) s
-5 129 M
-(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 18]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (18,19) 10
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 19 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Transport Layer Protocol Oct 2003) s
-5 690 M
-( byte SSH_MSG_KEXDH_INIT) s
-5 679 M
-( mpint e) s
-5 646 M
-( The server responds with the following:) s
-5 624 M
-( byte SSH_MSG_KEXDH_REPLY) s
-5 613 M
-( string server public host key and certificates \(K_S\)) s
-5 602 M
-( mpint f) s
-5 591 M
-( string signature of H) s
-5 569 M
-( The hash H is computed as the HASH hash of the concatenation of the) s
-5 558 M
-( following:) s
-5 536 M
-( string V_C, the client's version string \(CR and NL excluded\)) s
-5 525 M
-( string V_S, the server's version string \(CR and NL excluded\)) s
-5 514 M
-( string I_C, the payload of the client's SSH_MSG_KEXINIT) s
-5 503 M
-( string I_S, the payload of the server's SSH_MSG_KEXINIT) s
-5 492 M
-( string K_S, the host key) s
-5 481 M
-( mpint e, exchange value sent by the client) s
-5 470 M
-( mpint f, exchange value sent by the server) s
-5 459 M
-( mpint K, the shared secret) s
-5 437 M
-( This value is called the exchange hash, and it is used to) s
-5 426 M
-( authenticate the key exchange. The exchange hash SHOULD be kept) s
-5 415 M
-( secret.) s
-5 382 M
-( The signature algorithm MUST be applied over H, not the original) s
-5 371 M
-( data. Most signature algorithms include hashing and additional) s
-5 360 M
-( padding. For example, "ssh-dss" specifies SHA-1 hashing; in that) s
-5 349 M
-( case, the data is first hashed with HASH to compute H, and H is then) s
-5 338 M
-( hashed with SHA-1 as part of the signing operation.) s
-5 316 M
-(7.1 diffie-hellman-group1-sha1) s
-5 294 M
-( The "diffie-hellman-group1-sha1" method specifies Diffie-Hellman key) s
-5 283 M
-( exchange with SHA-1 as HASH, and Oakley group 14 [RFC3526] \(2048-bit) s
-5 272 M
-( MODP Group\). It is included below in hexadecimal and decimal.) s
-5 250 M
-( The prime p is equal to 2^1024 - 2^960 - 1 + 2^64 * floor\( 2^894 Pi +) s
-5 239 M
-( 129093 \). Its hexadecimal value is:) s
-5 217 M
-( FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1) s
-5 206 M
-( 29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD) s
-5 195 M
-( EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245) s
-5 184 M
-( E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED) s
-5 173 M
-( EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE65381) s
-5 129 M
-(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 19]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 20 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Transport Layer Protocol Oct 2003) s
-5 690 M
-( FFFFFFFF FFFFFFFF.) s
-5 668 M
-( In decimal, this value is:) s
-5 646 M
-( 179769313486231590770839156793787453197860296048756011706444) s
-5 635 M
-( 423684197180216158519368947833795864925541502180565485980503) s
-5 624 M
-( 646440548199239100050792877003355816639229553136239076508735) s
-5 613 M
-( 759914822574862575007425302077447712589550957937778424442426) s
-5 602 M
-( 617334727629299387668709205606050270810842907692932019128194) s
-5 591 M
-( 467627007.) s
-5 569 M
-( The generator used with this prime is g = 2. The group order q is \(p) s
-5 558 M
-( - 1\) / 2.) s
-5 536 M
-(8. Key Re-Exchange) s
-5 514 M
-( Key re-exchange is started by sending an SSH_MSG_KEXINIT packet when) s
-5 503 M
-( not already doing a key exchange \(as described in Section Section) s
-5 492 M
-( 6.1\). When this message is received, a party MUST respond with its) s
-5 481 M
-( own SSH_MSG_KEXINIT message except when the received SSH_MSG_KEXINIT) s
-5 470 M
-( already was a reply. Either party MAY initiate the re-exchange, but) s
-5 459 M
-( roles MUST NOT be changed \(i.e., the server remains the server, and) s
-5 448 M
-( the client remains the client\).) s
-5 415 M
-( Key re-exchange is performed using whatever encryption was in effect) s
-5 404 M
-( when the exchange was started. Encryption, compression, and MAC) s
-5 393 M
-( methods are not changed before a new SSH_MSG_NEWKEYS is sent after) s
-5 382 M
-( the key exchange \(as in the initial key exchange\). Re-exchange is) s
-5 371 M
-( processed identically to the initial key exchange, except for the) s
-5 360 M
-( session identifier that will remain unchanged. It is permissible to) s
-5 349 M
-( change some or all of the algorithms during the re-exchange. Host) s
-5 338 M
-( keys can also change. All keys and initialization vectors are) s
-5 327 M
-( recomputed after the exchange. Compression and encryption contexts) s
-5 316 M
-( are reset.) s
-5 283 M
-( It is recommended that the keys are changed after each gigabyte of) s
-5 272 M
-( transmitted data or after each hour of connection time, whichever) s
-5 261 M
-( comes sooner. However, since the re-exchange is a public key) s
-5 250 M
-( operation, it requires a fair amount of processing power and should) s
-5 239 M
-( not be performed too often.) s
-5 206 M
-( More application data may be sent after the SSH_MSG_NEWKEYS packet) s
-5 195 M
-( has been sent; key exchange does not affect the protocols that lie) s
-5 184 M
-( above the SSH transport layer.) s
-5 129 M
-(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 20]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (20,21) 11
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 21 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Transport Layer Protocol Oct 2003) s
-5 690 M
-(9. Service Request) s
-5 668 M
-( After the key exchange, the client requests a service. The service is) s
-5 657 M
-( identified by a name. The format of names and procedures for defining) s
-5 646 M
-( new names are defined in [SSH-ARCH].) s
-5 613 M
-( Currently, the following names have been reserved:) s
-5 591 M
-( ssh-userauth) s
-5 580 M
-( ssh-connection) s
-5 558 M
-( Similar local naming policy is applied to the service names, as is) s
-5 547 M
-( applied to the algorithm names; a local service should use the) s
-5 536 M
-( "servicename@domain" syntax.) s
-5 514 M
-( byte SSH_MSG_SERVICE_REQUEST) s
-5 503 M
-( string service name) s
-5 481 M
-( If the server rejects the service request, it SHOULD send an) s
-5 470 M
-( appropriate SSH_MSG_DISCONNECT message and MUST disconnect.) s
-5 437 M
-( When the service starts, it may have access to the session identifier) s
-5 426 M
-( generated during the key exchange.) s
-5 393 M
-( If the server supports the service \(and permits the client to use) s
-5 382 M
-( it\), it MUST respond with the following:) s
-5 360 M
-( byte SSH_MSG_SERVICE_ACCEPT) s
-5 349 M
-( string service name) s
-5 327 M
-( Message numbers used by services should be in the area reserved for) s
-5 316 M
-( them \(see Section 6 in [SSH-ARCH]\). The transport level will) s
-5 305 M
-( continue to process its own messages.) s
-5 272 M
-( Note that after a key exchange with implicit server authentication,) s
-5 261 M
-( the client MUST wait for response to its service request message) s
-5 250 M
-( before sending any further data.) s
-5 228 M
-(10. Additional Messages) s
-5 206 M
-( Either party may send any of the following messages at any time.) s
-5 129 M
-(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 21]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 22 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Transport Layer Protocol Oct 2003) s
-5 690 M
-(10.1 Disconnection Message) s
-5 668 M
-( byte SSH_MSG_DISCONNECT) s
-5 657 M
-( uint32 reason code) s
-5 646 M
-( string description [RFC2279]) s
-5 635 M
-( string language tag [RFC3066]) s
-5 613 M
-( This message causes immediate termination of the connection. All) s
-5 602 M
-( implementations MUST be able to process this message; they SHOULD be) s
-5 591 M
-( able to send this message.) s
-5 569 M
-( The sender MUST NOT send or receive any data after this message, and) s
-5 558 M
-( the recipient MUST NOT accept any data after receiving this message.) s
-5 547 M
-( The description field gives a more specific explanation in a) s
-5 536 M
-( human-readable form. The error code gives the reason in a more) s
-5 525 M
-( machine-readable format \(suitable for localization\), and can have the) s
-5 514 M
-( following values:) s
-5 492 M
-( #define SSH_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT 1) s
-5 481 M
-( #define SSH_DISCONNECT_PROTOCOL_ERROR 2) s
-5 470 M
-( #define SSH_DISCONNECT_KEY_EXCHANGE_FAILED 3) s
-5 459 M
-( #define SSH_DISCONNECT_RESERVED 4) s
-5 448 M
-( #define SSH_DISCONNECT_MAC_ERROR 5) s
-5 437 M
-( #define SSH_DISCONNECT_COMPRESSION_ERROR 6) s
-5 426 M
-( #define SSH_DISCONNECT_SERVICE_NOT_AVAILABLE 7) s
-5 415 M
-( #define SSH_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED 8) s
-5 404 M
-( #define SSH_DISCONNECT_HOST_KEY_NOT_VERIFIABLE 9) s
-5 393 M
-( #define SSH_DISCONNECT_CONNECTION_LOST 10) s
-5 382 M
-( #define SSH_DISCONNECT_BY_APPLICATION 11) s
-5 371 M
-( #define SSH_DISCONNECT_TOO_MANY_CONNECTIONS 12) s
-5 360 M
-( #define SSH_DISCONNECT_AUTH_CANCELLED_BY_USER 13) s
-5 349 M
-( #define SSH_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE 14) s
-5 338 M
-( #define SSH_DISCONNECT_ILLEGAL_USER_NAME 15) s
-5 316 M
-( If the description string is displayed, control character filtering) s
-5 305 M
-( discussed in [SSH-ARCH] should be used to avoid attacks by sending) s
-5 294 M
-( terminal control characters.) s
-5 272 M
-(10.2 Ignored Data Message) s
-5 250 M
-( byte SSH_MSG_IGNORE) s
-5 239 M
-( string data) s
-5 217 M
-( All implementations MUST understand \(and ignore\) this message at any) s
-5 206 M
-( time \(after receiving the protocol version\). No implementation is) s
-5 195 M
-( required to send them. This message can be used as an additional) s
-5 184 M
-( protection measure against advanced traffic analysis techniques.) s
-5 129 M
-(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 22]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (22,23) 12
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 23 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Transport Layer Protocol Oct 2003) s
-5 690 M
-(10.3 Debug Message) s
-5 668 M
-( byte SSH_MSG_DEBUG) s
-5 657 M
-( boolean always_display) s
-5 646 M
-( string message [RFC2279]) s
-5 635 M
-( string language tag [RFC3066]) s
-5 613 M
-( All implementations MUST understand this message, but they are) s
-5 602 M
-( allowed to ignore it. This message is used to pass the other side) s
-5 591 M
-( information that may help debugging. If always_display is TRUE, the) s
-5 580 M
-( message SHOULD be displayed. Otherwise, it SHOULD NOT be displayed) s
-5 569 M
-( unless debugging information has been explicitly requested by the) s
-5 558 M
-( user.) s
-5 525 M
-( The message doesn't need to contain a newline. It is, however,) s
-5 514 M
-( allowed to consist of multiple lines separated by CRLF \(Carriage) s
-5 503 M
-( Return - Line Feed\) pairs.) s
-5 470 M
-( If the message string is displayed, terminal control character) s
-5 459 M
-( filtering discussed in [SSH-ARCH] should be used to avoid attacks by) s
-5 448 M
-( sending terminal control characters.) s
-5 426 M
-(10.4 Reserved Messages) s
-5 404 M
-( An implementation MUST respond to all unrecognized messages with an) s
-5 393 M
-( SSH_MSG_UNIMPLEMENTED message in the order in which the messages were) s
-5 382 M
-( received. Such messages MUST be otherwise ignored. Later protocol) s
-5 371 M
-( versions may define other meanings for these message types.) s
-5 349 M
-( byte SSH_MSG_UNIMPLEMENTED) s
-5 338 M
-( uint32 packet sequence number of rejected message) s
-5 305 M
-(11. Summary of Message Numbers) s
-5 283 M
-( The following message numbers have been defined in this protocol:) s
-5 261 M
-( #define SSH_MSG_DISCONNECT 1) s
-5 250 M
-( #define SSH_MSG_IGNORE 2) s
-5 239 M
-( #define SSH_MSG_UNIMPLEMENTED 3) s
-5 228 M
-( #define SSH_MSG_DEBUG 4) s
-5 217 M
-( #define SSH_MSG_SERVICE_REQUEST 5) s
-5 206 M
-( #define SSH_MSG_SERVICE_ACCEPT 6) s
-5 184 M
-( #define SSH_MSG_KEXINIT 20) s
-5 173 M
-( #define SSH_MSG_NEWKEYS 21) s
-5 129 M
-(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 23]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 24 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Transport Layer Protocol Oct 2003) s
-5 690 M
-( /* Numbers 30-49 used for kex packets.) s
-5 679 M
-( Different kex methods may reuse message numbers in) s
-5 668 M
-( this range. */) s
-5 646 M
-( #define SSH_MSG_KEXDH_INIT 30) s
-5 635 M
-( #define SSH_MSG_KEXDH_REPLY 31) s
-5 602 M
-(12. IANA Considerations) s
-5 580 M
-( This document is part of a set, the IANA considerations for the SSH) s
-5 569 M
-( protocol as defined in [SSH-ARCH], [SSH-TRANS], [SSH-USERAUTH],) s
-5 558 M
-( [SSH-CONNECT] are detailed in [SSH-NUMBERS].) s
-5 536 M
-(13. Security Considerations) s
-5 514 M
-( This protocol provides a secure encrypted channel over an insecure) s
-5 503 M
-( network. It performs server host authentication, key exchange,) s
-5 492 M
-( encryption, and integrity protection. It also derives a unique) s
-5 481 M
-( session id that may be used by higher-level protocols.) s
-5 459 M
-( Full security considerations for this protocol are provided in) s
-5 448 M
-( Section 8 of [SSH-ARCH]) s
-5 426 M
-(14. Intellectual Property) s
-5 404 M
-( The IETF takes no position regarding the validity or scope of any) s
-5 393 M
-( intellectual property or other rights that might be claimed to) s
-5 382 M
-( pertain to the implementation or use of the technology described in) s
-5 371 M
-( this document or the extent to which any license under such rights) s
-5 360 M
-( might or might not be available; neither does it represent that it) s
-5 349 M
-( has made any effort to identify any such rights. Information on the) s
-5 338 M
-( IETF's procedures with respect to rights in standards-track and) s
-5 327 M
-( standards-related documentation can be found in BCP-11. Copies of) s
-5 316 M
-( claims of rights made available for publication and any assurances of) s
-5 305 M
-( licenses to be made available, or the result of an attempt made to) s
-5 294 M
-( obtain a general license or permission for the use of such) s
-5 283 M
-( proprietary rights by implementers or users of this specification can) s
-5 272 M
-( be obtained from the IETF Secretariat.) s
-5 250 M
-( The IETF has been notified of intellectual property rights claimed in) s
-5 239 M
-( regard to some or all of the specification contained in this) s
-5 228 M
-( document. For more information consult the online list of claimed) s
-5 217 M
-( rights.) s
-5 195 M
-(15. Additional Information) s
-5 173 M
-( The current document editor is: [email protected]. Comments on) s
-5 129 M
-(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 24]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (24,25) 13
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 25 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Transport Layer Protocol Oct 2003) s
-5 690 M
-( this internet draft should be sent to the IETF SECSH working group,) s
-5 679 M
-( details at: http://ietf.org/html.charters/secsh-charter.html) s
-5 657 M
-(Normative) s
-5 635 M
-( [SSH-ARCH]) s
-5 624 M
-( Ylonen, T., "SSH Protocol Architecture", I-D) s
-5 613 M
-( draft-ietf-architecture-15.txt, Oct 2003.) s
-5 591 M
-( [SSH-TRANS]) s
-5 580 M
-( Ylonen, T., "SSH Transport Layer Protocol", I-D) s
-5 569 M
-( draft-ietf-transport-17.txt, Oct 2003.) s
-5 547 M
-( [SSH-USERAUTH]) s
-5 536 M
-( Ylonen, T., "SSH Authentication Protocol", I-D) s
-5 525 M
-( draft-ietf-userauth-18.txt, Oct 2003.) s
-5 503 M
-( [SSH-CONNECT]) s
-5 492 M
-( Ylonen, T., "SSH Connection Protocol", I-D) s
-5 481 M
-( draft-ietf-connect-18.txt, Oct 2003.) s
-5 459 M
-( [SSH-NUMBERS]) s
-5 448 M
-( Lehtinen, S. and D. Moffat, "SSH Protocol Assigned) s
-5 437 M
-( Numbers", I-D draft-ietf-secsh-assignednumbers-05.txt, Oct) s
-5 426 M
-( 2003.) s
-5 404 M
-( [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate) s
-5 393 M
-( Requirement Levels", BCP 14, RFC 2119, March 1997.) s
-5 371 M
-(Informative) s
-5 349 M
-( [FIPS-186]) s
-5 338 M
-( Federal Information Processing Standards Publication,) s
-5 327 M
-( "FIPS PUB 186, Digital Signature Standard", May 1994.) s
-5 305 M
-( [FIPS-197]) s
-5 294 M
-( NIST, "FIPS PUB 197 Advanced Encryption Standard \(AES\)",) s
-5 283 M
-( November 2001.) s
-5 261 M
-( [FIPS-46-3]) s
-5 250 M
-( U.S. Dept. of Commerce, "FIPS PUB 46-3, Data Encryption) s
-5 239 M
-( Standard \(DES\)", October 1999.) s
-5 217 M
-( [RFC2459] Housley, R., Ford, W., Polk, T. and D. Solo, "Internet) s
-5 206 M
-( X.509 Public Key Infrastructure Certificate and CRL) s
-5 195 M
-( Profile", RFC 2459, January 1999.) s
-5 173 M
-( [RFC1034] Mockapetris, P., "Domain names - concepts and facilities",) s
-5 129 M
-(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 25]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 26 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Transport Layer Protocol Oct 2003) s
-5 690 M
-( STD 13, RFC 1034, November 1987.) s
-5 668 M
-( [RFC3066] Alvestrand, H., "Tags for the Identification of) s
-5 657 M
-( Languages", BCP 47, RFC 3066, January 2001.) s
-5 635 M
-( [RFC1950] Deutsch, L. and J-L. Gailly, "ZLIB Compressed Data Format) s
-5 624 M
-( Specification version 3.3", RFC 1950, May 1996.) s
-5 602 M
-( [RFC1951] Deutsch, P., "DEFLATE Compressed Data Format Specification) s
-5 591 M
-( version 1.3", RFC 1951, May 1996.) s
-5 569 M
-( [RFC2279] Yergeau, F., "UTF-8, a transformation format of ISO) s
-5 558 M
-( 10646", RFC 2279, January 1998.) s
-5 536 M
-( [RFC2104] Krawczyk, H., Bellare, M. and R. Canetti, "HMAC:) s
-5 525 M
-( Keyed-Hashing for Message Authentication", RFC 2104,) s
-5 514 M
-( February 1997.) s
-5 492 M
-( [RFC2144] Adams, C., "The CAST-128 Encryption Algorithm", RFC 2144,) s
-5 481 M
-( May 1997.) s
-5 459 M
-( [RFC2440] Callas, J., Donnerhacke, L., Finney, H. and R. Thayer,) s
-5 448 M
-( "OpenPGP Message Format", RFC 2440, November 1998.) s
-5 426 M
-( [RFC2693] Ellison, C., Frantz, B., Lampson, B., Rivest, R., Thomas,) s
-5 415 M
-( B. and T. Ylonen, "SPKI Certificate Theory", RFC 2693,) s
-5 404 M
-( September 1999.) s
-5 382 M
-( [RFC3526] Kivinen, T. and M. Kojo, "More Modular Exponential \(MODP\)) s
-5 371 M
-( Diffie-Hellman groups for Internet Key Exchange \(IKE\)",) s
-5 360 M
-( RFC 3526, May 2003.) s
-5 338 M
-( [SCHNEIER]) s
-5 327 M
-( Schneier, B., "Applied Cryptography Second Edition:) s
-5 316 M
-( protocols algorithms and source in code in C", 1996.) s
-5 294 M
-( [TWOFISH] Schneier, B., "The Twofish Encryptions Algorithm: A) s
-5 283 M
-( 128-Bit Block Cipher, 1st Edition", March 1999.) s
-5 129 M
-(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 26]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (26,27) 14
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 27 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Transport Layer Protocol Oct 2003) s
-5 690 M
-(Authors' Addresses) s
-5 668 M
-( Tatu Ylonen) s
-5 657 M
-( SSH Communications Security Corp) s
-5 646 M
-( Fredrikinkatu 42) s
-5 635 M
-( HELSINKI FIN-00100) s
-5 624 M
-( Finland) s
-5 602 M
-( EMail: [email protected]) s
-5 569 M
-( Darren J. Moffat \(editor\)) s
-5 558 M
-( Sun Microsystems, Inc) s
-5 547 M
-( 17 Network Circle) s
-5 536 M
-( Menlo Park 95025) s
-5 525 M
-( USA) s
-5 503 M
-( EMail: [email protected]) s
-5 481 M
-(Appendix A. Contibutors) s
-5 129 M
-(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 27]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 28 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Transport Layer Protocol Oct 2003) s
-5 690 M
-(Intellectual Property Statement) s
-5 668 M
-( The IETF takes no position regarding the validity or scope of any) s
-5 657 M
-( intellectual property or other rights that might be claimed to) s
-5 646 M
-( pertain to the implementation or use of the technology described in) s
-5 635 M
-( this document or the extent to which any license under such rights) s
-5 624 M
-( might or might not be available; neither does it represent that it) s
-5 613 M
-( has made any effort to identify any such rights. Information on the) s
-5 602 M
-( IETF's procedures with respect to rights in standards-track and) s
-5 591 M
-( standards-related documentation can be found in BCP-11. Copies of) s
-5 580 M
-( claims of rights made available for publication and any assurances of) s
-5 569 M
-( licenses to be made available, or the result of an attempt made to) s
-5 558 M
-( obtain a general license or permission for the use of such) s
-5 547 M
-( proprietary rights by implementors or users of this specification can) s
-5 536 M
-( be obtained from the IETF Secretariat.) s
-5 514 M
-( The IETF invites any interested party to bring to its attention any) s
-5 503 M
-( copyrights, patents or patent applications, or other proprietary) s
-5 492 M
-( rights which may cover technology that may be required to practice) s
-5 481 M
-( this standard. Please address the information to the IETF Executive) s
-5 470 M
-( Director.) s
-5 448 M
-( The IETF has been notified of intellectual property rights claimed in) s
-5 437 M
-( regard to some or all of the specification contained in this) s
-5 426 M
-( document. For more information consult the online list of claimed) s
-5 415 M
-( rights.) s
-5 382 M
-(Full Copyright Statement) s
-5 360 M
-( Copyright \(C\) The Internet Society \(2003\). All Rights Reserved.) s
-5 338 M
-( This document and translations of it may be copied and furnished to) s
-5 327 M
-( others, and derivative works that comment on or otherwise explain it) s
-5 316 M
-( or assist in its implementation may be prepared, copied, published) s
-5 305 M
-( and distributed, in whole or in part, without restriction of any) s
-5 294 M
-( kind, provided that the above copyright notice and this paragraph are) s
-5 283 M
-( included on all such copies and derivative works. However, this) s
-5 272 M
-( document itself may not be modified in any way, such as by removing) s
-5 261 M
-( the copyright notice or references to the Internet Society or other) s
-5 250 M
-( Internet organizations, except as needed for the purpose of) s
-5 239 M
-( developing Internet standards in which case the procedures for) s
-5 228 M
-( copyrights defined in the Internet Standards process must be) s
-5 217 M
-( followed, or as required to translate it into languages other than) s
-5 206 M
-( English.) s
-5 184 M
-( The limited permissions granted above are perpetual and will not be) s
-5 173 M
-( revoked by the Internet Society or its successors or assignees.) s
-5 129 M
-(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 28]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (28,29) 15
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 29 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Transport Layer Protocol Oct 2003) s
-5 690 M
-( This document and the information contained herein is provided on an) s
-5 679 M
-( "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING) s
-5 668 M
-( TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING) s
-5 657 M
-( BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION) s
-5 646 M
-( HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF) s
-5 635 M
-( MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.) s
-5 602 M
-(Acknowledgment) s
-5 580 M
-( Funding for the RFC Editor function is currently provided by the) s
-5 569 M
-( Internet Society.) s
-5 129 M
-(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 29]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-showpage
-PStoPSsaved restore
-%%Trailer
-%%Pages: 29
-%%DocumentNeededResources: font Courier-Bold Courier
-%%EOF
diff --git a/lib/ssh/doc/standard/draft-ietf-secsh-transport-17.txt b/lib/ssh/doc/standard/draft-ietf-secsh-transport-17.txt
deleted file mode 100644
index 9073ea52b2..0000000000
--- a/lib/ssh/doc/standard/draft-ietf-secsh-transport-17.txt
+++ /dev/null
@@ -1,1624 +0,0 @@
-
-
-
-Network Working Group T. Ylonen
-Internet-Draft SSH Communications Security Corp
-Expires: March 31, 2004 D. Moffat, Editor, Ed.
- Sun Microsystems, Inc
- Oct 2003
-
-
- SSH Transport Layer Protocol
- draft-ietf-secsh-transport-17.txt
-
-Status of this Memo
-
- This document is an Internet-Draft and is in full conformance with
- all provisions of Section 10 of RFC2026.
-
- Internet-Drafts are working documents of the Internet Engineering
- Task Force (IETF), its areas, and its working groups. Note that other
- groups may also distribute working documents as Internet-Drafts.
-
- Internet-Drafts are draft documents valid for a maximum of six months
- and may be updated, replaced, or obsoleted by other documents at any
- time. It is inappropriate to use Internet-Drafts as reference
- material or to cite them other than as "work in progress."
-
- The list of current Internet-Drafts can be accessed at http://
- www.ietf.org/ietf/1id-abstracts.txt.
-
- The list of Internet-Draft Shadow Directories can be accessed at
- http://www.ietf.org/shadow.html.
-
- This Internet-Draft will expire on March 31, 2004.
-
-Copyright Notice
-
- Copyright (C) The Internet Society (2003). All Rights Reserved.
-
-Abstract
-
- SSH is a protocol for secure remote login and other secure network
- services over an insecure network.
-
- This document describes the SSH transport layer protocol which
- typically runs on top of TCP/IP. The protocol can be used as a basis
- for a number of secure network services. It provides strong
- encryption, server authentication, and integrity protection. It may
- also provide compression.
-
- Key exchange method, public key algorithm, symmetric encryption
- algorithm, message authentication algorithm, and hash algorithm are
-
-
-
-Ylonen & Moffat, Editor Expires March 31, 2004 [Page 1]
-
-Internet-Draft SSH Transport Layer Protocol Oct 2003
-
-
- all negotiated.
-
- This document also describes the Diffie-Hellman key exchange method
- and the minimal set of algorithms that are needed to implement the
- SSH transport layer protocol.
-
-Table of Contents
-
- 1. Contributors . . . . . . . . . . . . . . . . . . . . . . . . 3
- 2. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3
- 3. Conventions Used in This Document . . . . . . . . . . . . . 3
- 4. Connection Setup . . . . . . . . . . . . . . . . . . . . . . 3
- 4.1 Use over TCP/IP . . . . . . . . . . . . . . . . . . . . . . 4
- 4.2 Protocol Version Exchange . . . . . . . . . . . . . . . . . 4
- 4.3 Compatibility With Old SSH Versions . . . . . . . . . . . . 4
- 4.3.1 Old Client, New Server . . . . . . . . . . . . . . . . . . . 5
- 4.3.2 New Client, Old Server . . . . . . . . . . . . . . . . . . . 5
- 5. Binary Packet Protocol . . . . . . . . . . . . . . . . . . . 5
- 5.1 Maximum Packet Length . . . . . . . . . . . . . . . . . . . 6
- 5.2 Compression . . . . . . . . . . . . . . . . . . . . . . . . 7
- 5.3 Encryption . . . . . . . . . . . . . . . . . . . . . . . . . 7
- 5.4 Data Integrity . . . . . . . . . . . . . . . . . . . . . . . 9
- 5.5 Key Exchange Methods . . . . . . . . . . . . . . . . . . . . 10
- 5.6 Public Key Algorithms . . . . . . . . . . . . . . . . . . . 11
- 6. Key Exchange . . . . . . . . . . . . . . . . . . . . . . . . 13
- 6.1 Algorithm Negotiation . . . . . . . . . . . . . . . . . . . 13
- 6.2 Output from Key Exchange . . . . . . . . . . . . . . . . . . 16
- 6.3 Taking Keys Into Use . . . . . . . . . . . . . . . . . . . . 17
- 7. Diffie-Hellman Key Exchange . . . . . . . . . . . . . . . . 18
- 7.1 diffie-hellman-group1-sha1 . . . . . . . . . . . . . . . . . 19
- 8. Key Re-Exchange . . . . . . . . . . . . . . . . . . . . . . 20
- 9. Service Request . . . . . . . . . . . . . . . . . . . . . . 21
- 10. Additional Messages . . . . . . . . . . . . . . . . . . . . 21
- 10.1 Disconnection Message . . . . . . . . . . . . . . . . . . . 22
- 10.2 Ignored Data Message . . . . . . . . . . . . . . . . . . . . 22
- 10.3 Debug Message . . . . . . . . . . . . . . . . . . . . . . . 23
- 10.4 Reserved Messages . . . . . . . . . . . . . . . . . . . . . 23
- 11. Summary of Message Numbers . . . . . . . . . . . . . . . . . 23
- 12. IANA Considerations . . . . . . . . . . . . . . . . . . . . 24
- 13. Security Considerations . . . . . . . . . . . . . . . . . . 24
- 14. Intellectual Property . . . . . . . . . . . . . . . . . . . 24
- 15. Additional Information . . . . . . . . . . . . . . . . . . . 24
- Authors' Addresses . . . . . . . . . . . . . . . . . . . . . 26
- Normative . . . . . . . . . . . . . . . . . . . . . . . . . 25
- Informative . . . . . . . . . . . . . . . . . . . . . . . . 25
- A. Contibutors . . . . . . . . . . . . . . . . . . . . . . . . 27
- Intellectual Property and Copyright Statements . . . . . . . 28
-
-
-
-
-Ylonen & Moffat, Editor Expires March 31, 2004 [Page 2]
-
-Internet-Draft SSH Transport Layer Protocol Oct 2003
-
-
-1. Contributors
-
- The major original contributors of this document were: Tatu Ylonen,
- Tero Kivinen, Timo J. Rinne, Sami Lehtinen (all of SSH Communications
- Security Corp), and Markku-Juhani O. Saarinen (University of
- Jyvaskyla)
-
- The document editor is: [email protected]. Comments on this
- internet draft should be sent to the IETF SECSH working group,
- details at: http://ietf.org/html.charters/secsh-charter.html
-
-2. Introduction
-
- The SSH transport layer is a secure low level transport protocol. It
- provides strong encryption, cryptographic host authentication, and
- integrity protection.
-
- Authentication in this protocol level is host-based; this protocol
- does not perform user authentication. A higher level protocol for
- user authentication can be designed on top of this protocol.
-
- The protocol has been designed to be simple, flexible, to allow
- parameter negotiation, and to minimize the number of round-trips.
- Key exchange method, public key algorithm, symmetric encryption
- algorithm, message authentication algorithm, and hash algorithm are
- all negotiated. It is expected that in most environments, only 2
- round-trips will be needed for full key exchange, server
- authentication, service request, and acceptance notification of
- service request. The worst case is 3 round-trips.
-
-3. Conventions Used in This Document
-
- The keywords "MUST", "MUST NOT", "REQUIRED", "SHOULD", "SHOULD NOT",
- and "MAY" that appear in this document are to be interpreted as
- described in [RFC2119].
-
- The used data types and terminology are specified in the architecture
- document [SSH-ARCH].
-
- The architecture document also discusses the algorithm naming
- conventions that MUST be used with the SSH protocols.
-
-4. Connection Setup
-
- SSH works over any 8-bit clean, binary-transparent transport. The
- underlying transport SHOULD protect against transmission errors as
- such errors cause the SSH connection to terminate.
-
-
-
-
-Ylonen & Moffat, Editor Expires March 31, 2004 [Page 3]
-
-Internet-Draft SSH Transport Layer Protocol Oct 2003
-
-
- The client initiates the connection.
-
-4.1 Use over TCP/IP
-
- When used over TCP/IP, the server normally listens for connections on
- port 22. This port number has been registered with the IANA, and has
- been officially assigned for SSH.
-
-4.2 Protocol Version Exchange
-
- When the connection has been established, both sides MUST send an
- identification string of the form "SSH-protoversion-softwareversion
- comments", followed by carriage return and newline characters (ASCII
- 13 and 10, respectively). Both sides MUST be able to process
- identification strings without carriage return character. No null
- character is sent. The maximum length of the string is 255
- characters, including the carriage return and newline.
-
- The part of the identification string preceding carriage return and
- newline is used in the Diffie-Hellman key exchange (see Section
- Section 7).
-
- The server MAY send other lines of data before sending the version
- string. Each line SHOULD be terminated by a carriage return and
- newline. Such lines MUST NOT begin with "SSH-", and SHOULD be
- encoded in ISO-10646 UTF-8 [RFC2279] (language is not specified).
- Clients MUST be able to process such lines; they MAY be silently
- ignored, or MAY be displayed to the client user; if they are
- displayed, control character filtering discussed in [SSH-ARCH] SHOULD
- be used. The primary use of this feature is to allow TCP-wrappers to
- display an error message before disconnecting.
-
- Version strings MUST consist of printable US-ASCII characters, not
- including whitespaces or a minus sign (-). The version string is
- primarily used to trigger compatibility extensions and to indicate
- the capabilities of an implementation. The comment string should
- contain additional information that might be useful in solving user
- problems.
-
- The protocol version described in this document is 2.0.
-
- Key exchange will begin immediately after sending this identifier.
- All packets following the identification string SHALL use the binary
- packet protocol, to be described below.
-
-4.3 Compatibility With Old SSH Versions
-
- During the transition period, it is important to be able to work in a
-
-
-
-Ylonen & Moffat, Editor Expires March 31, 2004 [Page 4]
-
-Internet-Draft SSH Transport Layer Protocol Oct 2003
-
-
- way that is compatible with the installed SSH clients and servers
- that use an older version of the protocol. Information in this
- section is only relevant for implementations supporting compatibility
- with SSH versions 1.x. There is no standards track or informational
- draft available that defines the SSH 1.x protocol. The only known
- documentation of the 1.x protocol is contained in README files that
- are shipped along with the source code.
-
-4.3.1 Old Client, New Server
-
- Server implementations MAY support a configurable "compatibility"
- flag that enables compatibility with old versions. When this flag is
- on, the server SHOULD identify its protocol version as "1.99".
- Clients using protocol 2.0 MUST be able to identify this as identical
- to "2.0". In this mode the server SHOULD NOT send the carriage
- return character (ASCII 13) after the version identification string.
-
- In the compatibility mode the server SHOULD NOT send any further data
- after its initialization string until it has received an
- identification string from the client. The server can then determine
- whether the client is using an old protocol, and can revert to the
- old protocol if required. In the compatibility mode, the server MUST
- NOT send additional data before the version string.
-
- When compatibility with old clients is not needed, the server MAY
- send its initial key exchange data immediately after the
- identification string.
-
-4.3.2 New Client, Old Server
-
- Since the new client MAY immediately send additional data after its
- identification string (before receiving server's identification), the
- old protocol may already have been corrupted when the client learns
- that the server is old. When this happens, the client SHOULD close
- the connection to the server, and reconnect using the old protocol.
-
-5. Binary Packet Protocol
-
- Each packet is in the following format:
-
- uint32 packet_length
- byte padding_length
- byte[n1] payload; n1 = packet_length - padding_length - 1
- byte[n2] random padding; n2 = padding_length
- byte[m] mac (message authentication code); m = mac_length
-
- packet_length
-
-
-
-
-Ylonen & Moffat, Editor Expires March 31, 2004 [Page 5]
-
-Internet-Draft SSH Transport Layer Protocol Oct 2003
-
-
- The length of the packet (bytes), not including MAC or the
- packet_length field itself.
-
- padding_length
- Length of padding (bytes).
-
- payload
- The useful contents of the packet. If compression has been
- negotiated, this field is compressed. Initially, compression
- MUST be "none".
-
- random padding
- Arbitrary-length padding, such that the total length of
- (packet_length || padding_length || payload || padding) is a
- multiple of the cipher block size or 8, whichever is larger.
- There MUST be at least four bytes of padding. The padding
- SHOULD consist of random bytes. The maximum amount of padding
- is 255 bytes.
-
- mac
- Message authentication code. If message authentication has
- been negotiated, this field contains the MAC bytes. Initially,
- the MAC algorithm MUST be "none".
-
-
- Note that length of the concatenation of packet length, padding
- length, payload, and padding MUST be a multiple of the cipher block
- size or 8, whichever is larger. This constraint MUST be enforced
- even when using stream ciphers. Note that the packet length field is
- also encrypted, and processing it requires special care when sending
- or receiving packets.
-
- The minimum size of a packet is 16 (or the cipher block size,
- whichever is larger) bytes (plus MAC); implementations SHOULD decrypt
- the length after receiving the first 8 (or cipher block size,
- whichever is larger) bytes of a packet.
-
-5.1 Maximum Packet Length
-
- All implementations MUST be able to process packets with uncompressed
- payload length of 32768 bytes or less and total packet size of 35000
- bytes or less (including length, padding length, payload, padding,
- and MAC.). The maximum of 35000 bytes is an arbitrary chosen value
- larger than uncompressed size. Implementations SHOULD support longer
- packets, where they might be needed, e.g. if an implementation wants
- to send a very large number of certificates. Such packets MAY be
- sent if the version string indicates that the other party is able to
- process them. However, implementations SHOULD check that the packet
-
-
-
-Ylonen & Moffat, Editor Expires March 31, 2004 [Page 6]
-
-Internet-Draft SSH Transport Layer Protocol Oct 2003
-
-
- length is reasonable for the implementation to avoid
- denial-of-service and/or buffer overflow attacks.
-
-5.2 Compression
-
- If compression has been negotiated, the payload field (and only it)
- will be compressed using the negotiated algorithm. The length field
- and MAC will be computed from the compressed payload. Encryption will
- be done after compression.
-
- Compression MAY be stateful, depending on the method. Compression
- MUST be independent for each direction, and implementations MUST
- allow independently choosing the algorithm for each direction.
-
- The following compression methods are currently defined:
-
- none REQUIRED no compression
- zlib OPTIONAL ZLIB (LZ77) compression
-
- The "zlib" compression is described in [RFC1950] and in [RFC1951].
- The compression context is initialized after each key exchange, and
- is passed from one packet to the next with only a partial flush being
- performed at the end of each packet. A partial flush means that the
- current compressed block is ended and all data will be output. If the
- current block is not a stored block, one or more empty blocks are
- added after the current block to ensure that there are at least 8
- bits counting from the start of the end-of-block code of the current
- block to the end of the packet payload.
-
- Additional methods may be defined as specified in [SSH-ARCH].
-
-5.3 Encryption
-
- An encryption algorithm and a key will be negotiated during the key
- exchange. When encryption is in effect, the packet length, padding
- length, payload and padding fields of each packet MUST be encrypted
- with the given algorithm.
-
- The encrypted data in all packets sent in one direction SHOULD be
- considered a single data stream. For example, initialization vectors
- SHOULD be passed from the end of one packet to the beginning of the
- next packet. All ciphers SHOULD use keys with an effective key length
- of 128 bits or more.
-
- The ciphers in each direction MUST run independently of each other,
- and implementations MUST allow independently choosing the algorithm
- for each direction (if multiple algorithms are allowed by local
- policy).
-
-
-
-Ylonen & Moffat, Editor Expires March 31, 2004 [Page 7]
-
-Internet-Draft SSH Transport Layer Protocol Oct 2003
-
-
- The following ciphers are currently defined:
-
- 3des-cbc REQUIRED three-key 3DES in CBC mode
- blowfish-cbc OPTIONALi Blowfish in CBC mode
- twofish256-cbc OPTIONAL Twofish in CBC mode,
- with 256-bit key
- twofish-cbc OPTIONAL alias for "twofish256-cbc" (this
- is being retained for
- historical reasons)
- twofish192-cbc OPTIONAL Twofish with 192-bit key
- twofish128-cbc OPTIONAL Twofish with 128-bit key
- aes256-cbc OPTIONAL AES (Rijndael) in CBC mode,
- with 256-bit key
- aes192-cbc OPTIONAL AES with 192-bit key
- aes128-cbc RECOMMENDED AES with 128-bit key
- serpent256-cbc OPTIONAL Serpent in CBC mode, with
- 256-bit key
- serpent192-cbc OPTIONAL Serpent with 192-bit key
- serpent128-cbc OPTIONAL Serpent with 128-bit key
- arcfour OPTIONAL the ARCFOUR stream cipher
- idea-cbc OPTIONAL IDEA in CBC mode
- cast128-cbc OPTIONAL CAST-128 in CBC mode
- none OPTIONAL no encryption; NOT RECOMMENDED
-
- The "3des-cbc" cipher is three-key triple-DES
- (encrypt-decrypt-encrypt), where the first 8 bytes of the key are
- used for the first encryption, the next 8 bytes for the decryption,
- and the following 8 bytes for the final encryption. This requires 24
- bytes of key data (of which 168 bits are actually used). To
- implement CBC mode, outer chaining MUST be used (i.e., there is only
- one initialization vector). This is a block cipher with 8 byte
- blocks. This algorithm is defined in [FIPS-46-3]
-
- The "blowfish-cbc" cipher is Blowfish in CBC mode, with 128 bit keys
- [SCHNEIER]. This is a block cipher with 8 byte blocks.
-
- The "twofish-cbc" or "twofish256-cbc" cipher is Twofish in CBC mode,
- with 256 bit keys as described [TWOFISH]. This is a block cipher with
- 16 byte blocks.
-
- The "twofish192-cbc" cipher. Same as above but with 192-bit key.
-
- The "twofish128-cbc" cipher. Same as above but with 128-bit key.
-
- The "aes256-cbc" cipher is AES (Advanced Encryption Standard)
- [FIPS-197], formerly Rijndael, in CBC mode. This version uses 256-bit
- key.
-
-
-
-
-Ylonen & Moffat, Editor Expires March 31, 2004 [Page 8]
-
-Internet-Draft SSH Transport Layer Protocol Oct 2003
-
-
- The "aes192-cbc" cipher. Same as above but with 192-bit key.
-
- The "aes128-cbc" cipher. Same as above but with 128-bit key.
-
- The "serpent256-cbc" cipher in CBC mode, with 256-bit key as
- described in the Serpent AES submission.
-
- The "serpent192-cbc" cipher. Same as above but with 192-bit key.
-
- The "serpent128-cbc" cipher. Same as above but with 128-bit key.
-
- The "arcfour" is the Arcfour stream cipher with 128 bit keys. The
- Arcfour cipher is believed to be compatible with the RC4 cipher
- [SCHNEIER]. RC4 is a registered trademark of RSA Data Security Inc.
- Arcfour (and RC4) has problems with weak keys, and should be used
- with caution.
-
- The "idea-cbc" cipher is the IDEA cipher in CBC mode [SCHNEIER].
-
- The "cast128-cbc" cipher is the CAST-128 cipher in CBC mode
- [RFC2144].
-
- The "none" algorithm specifies that no encryption is to be done.
- Note that this method provides no confidentiality protection, and it
- is not recommended. Some functionality (e.g. password
- authentication) may be disabled for security reasons if this cipher
- is chosen.
-
- Additional methods may be defined as specified in [SSH-ARCH].
-
-5.4 Data Integrity
-
- Data integrity is protected by including with each packet a message
- authentication code (MAC) that is computed from a shared secret,
- packet sequence number, and the contents of the packet.
-
- The message authentication algorithm and key are negotiated during
- key exchange. Initially, no MAC will be in effect, and its length
- MUST be zero. After key exchange, the selected MAC will be computed
- before encryption from the concatenation of packet data:
-
- mac = MAC(key, sequence_number || unencrypted_packet)
-
- where unencrypted_packet is the entire packet without MAC (the length
- fields, payload and padding), and sequence_number is an implicit
- packet sequence number represented as uint32. The sequence number is
- initialized to zero for the first packet, and is incremented after
- every packet (regardless of whether encryption or MAC is in use). It
-
-
-
-Ylonen & Moffat, Editor Expires March 31, 2004 [Page 9]
-
-Internet-Draft SSH Transport Layer Protocol Oct 2003
-
-
- is never reset, even if keys/algorithms are renegotiated later. It
- wraps around to zero after every 2^32 packets. The packet sequence
- number itself is not included in the packet sent over the wire.
-
- The MAC algorithms for each direction MUST run independently, and
- implementations MUST allow choosing the algorithm independently for
- both directions.
-
- The MAC bytes resulting from the MAC algorithm MUST be transmitted
- without encryption as the last part of the packet. The number of MAC
- bytes depends on the algorithm chosen.
-
- The following MAC algorithms are currently defined:
-
- hmac-sha1 REQUIRED HMAC-SHA1 (digest length = key
- length = 20)
- hmac-sha1-96 RECOMMENDED first 96 bits of HMAC-SHA1 (digest
- length = 12, key length = 20)
- hmac-md5 OPTIONAL HMAC-MD5 (digest length = key
- length = 16)
- hmac-md5-96 OPTIONAL first 96 bits of HMAC-MD5 (digest
- length = 12, key length = 16)
- none OPTIONAL no MAC; NOT RECOMMENDED
-
- Figure 1
-
- The "hmac-*" algorithms are described in [RFC2104] The "*-n" MACs use
- only the first n bits of the resulting value.
-
- The hash algorithms are described in [SCHNEIER].
-
- Additional methods may be defined as specified in [SSH-ARCH].
-
-5.5 Key Exchange Methods
-
- The key exchange method specifies how one-time session keys are
- generated for encryption and for authentication, and how the server
- authentication is done.
-
- Only one REQUIRED key exchange method has been defined:
-
- diffie-hellman-group1-sha1 REQUIRED
-
- This method is described later in this document.
-
- Additional methods may be defined as specified in [SSH-ARCH].
-
-
-
-
-
-Ylonen & Moffat, Editor Expires March 31, 2004 [Page 10]
-
-Internet-Draft SSH Transport Layer Protocol Oct 2003
-
-
-5.6 Public Key Algorithms
-
- This protocol has been designed to be able to operate with almost any
- public key format, encoding, and algorithm (signature and/or
- encryption).
-
- There are several aspects that define a public key type:
- o Key format: how is the key encoded and how are certificates
- represented. The key blobs in this protocol MAY contain
- certificates in addition to keys.
- o Signature and/or encryption algorithms. Some key types may not
- support both signing and encryption. Key usage may also be
- restricted by policy statements in e.g. certificates. In this
- case, different key types SHOULD be defined for the different
- policy alternatives.
- o Encoding of signatures and/or encrypted data. This includes but is
- not limited to padding, byte order, and data formats.
-
- The following public key and/or certificate formats are currently defined:
-
- ssh-dss REQUIRED sign Raw DSS Key
- ssh-rsa RECOMMENDED sign Raw RSA Key
- x509v3-sign-rsa OPTIONAL sign X.509 certificates (RSA key)
- x509v3-sign-dss OPTIONAL sign X.509 certificates (DSS key)
- spki-sign-rsa OPTIONAL sign SPKI certificates (RSA key)
- spki-sign-dss OPTIONAL sign SPKI certificates (DSS key)
- pgp-sign-rsa OPTIONAL sign OpenPGP certificates (RSA key)
- pgp-sign-dss OPTIONAL sign OpenPGP certificates (DSS key)
-
- Additional key types may be defined as specified in [SSH-ARCH].
-
- The key type MUST always be explicitly known (from algorithm
- negotiation or some other source). It is not normally included in
- the key blob.
-
- Certificates and public keys are encoded as follows:
-
- string certificate or public key format identifier
- byte[n] key/certificate data
-
- The certificate part may have be a zero length string, but a public
- key is required. This is the public key that will be used for
- authentication; the certificate sequence contained in the certificate
- blob can be used to provide authorization.
-
- Public key / certifcate formats that do not explicitly specify a
- signature format identifier MUST use the public key / certificate
- format identifier as the signature identifier.
-
-
-
-Ylonen & Moffat, Editor Expires March 31, 2004 [Page 11]
-
-Internet-Draft SSH Transport Layer Protocol Oct 2003
-
-
- Signatures are encoded as follows:
- string signature format identifier (as specified by the
- public key / cert format)
- byte[n] signature blob in format specific encoding.
-
-
- The "ssh-dss" key format has the following specific encoding:
-
- string "ssh-dss"
- mpint p
- mpint q
- mpint g
- mpint y
-
- Here the p, q, g, and y parameters form the signature key blob.
-
- Signing and verifying using this key format is done according to the
- Digital Signature Standard [FIPS-186] using the SHA-1 hash. A
- description can also be found in [SCHNEIER].
-
- The resulting signature is encoded as follows:
-
- string "ssh-dss"
- string dss_signature_blob
-
- dss_signature_blob is encoded as a string containing r followed by s
- (which are 160 bits long integers, without lengths or padding,
- unsigned and in network byte order).
-
- The "ssh-rsa" key format has the following specific encoding:
-
- string "ssh-rsa"
- mpint e
- mpint n
-
- Here the e and n parameters form the signature key blob.
-
- Signing and verifying using this key format is done according to
- [SCHNEIER] and [PKCS1] using the SHA-1 hash.
-
- The resulting signature is encoded as follows:
-
- string "ssh-rsa"
- string rsa_signature_blob
-
- rsa_signature_blob is encoded as a string containing s (which is an
- integer, without lengths or padding, unsigned and in network byte
- order).
-
-
-
-Ylonen & Moffat, Editor Expires March 31, 2004 [Page 12]
-
-Internet-Draft SSH Transport Layer Protocol Oct 2003
-
-
- The "spki-sign-rsa" method indicates that the certificate blob
- contains a sequence of SPKI certificates. The format of SPKI
- certificates is described in [RFC2693]. This method indicates that
- the key (or one of the keys in the certificate) is an RSA-key.
-
- The "spki-sign-dss". As above, but indicates that the key (or one of
- the keys in the certificate) is a DSS-key.
-
- The "pgp-sign-rsa" method indicates the certificates, the public key,
- and the signature are in OpenPGP compatible binary format
- ([RFC2440]). This method indicates that the key is an RSA-key.
-
- The "pgp-sign-dss". As above, but indicates that the key is a
- DSS-key.
-
-6. Key Exchange
-
- Key exchange begins by each side sending lists of supported
- algorithms. Each side has a preferred algorithm in each category, and
- it is assumed that most implementations at any given time will use
- the same preferred algorithm. Each side MAY guess which algorithm
- the other side is using, and MAY send an initial key exchange packet
- according to the algorithm if appropriate for the preferred method.
-
- Guess is considered wrong, if:
- o the kex algorithm and/or the host key algorithm is guessed wrong
- (server and client have different preferred algorithm), or
- o if any of the other algorithms cannot be agreed upon (the
- procedure is defined below in Section Section 6.1).
-
- Otherwise, the guess is considered to be right and the optimistically
- sent packet MUST be handled as the first key exchange packet.
-
- However, if the guess was wrong, and a packet was optimistically sent
- by one or both parties, such packets MUST be ignored (even if the
- error in the guess would not affect the contents of the initial
- packet(s)), and the appropriate side MUST send the correct initial
- packet.
-
- Server authentication in the key exchange MAY be implicit. After a
- key exchange with implicit server authentication, the client MUST
- wait for response to its service request message before sending any
- further data.
-
-6.1 Algorithm Negotiation
-
- Key exchange begins by each side sending the following packet:
-
-
-
-
-Ylonen & Moffat, Editor Expires March 31, 2004 [Page 13]
-
-Internet-Draft SSH Transport Layer Protocol Oct 2003
-
-
- byte SSH_MSG_KEXINIT
- byte[16] cookie (random bytes)
- string kex_algorithms
- string server_host_key_algorithms
- string encryption_algorithms_client_to_server
- string encryption_algorithms_server_to_client
- string mac_algorithms_client_to_server
- string mac_algorithms_server_to_client
- string compression_algorithms_client_to_server
- string compression_algorithms_server_to_client
- string languages_client_to_server
- string languages_server_to_client
- boolean first_kex_packet_follows
- uint32 0 (reserved for future extension)
-
- Each of the algorithm strings MUST be a comma-separated list of
- algorithm names (see ''Algorithm Naming'' in [SSH-ARCH]). Each
- supported (allowed) algorithm MUST be listed in order of preference.
-
- The first algorithm in each list MUST be the preferred (guessed)
- algorithm. Each string MUST contain at least one algorithm name.
-
-
- cookie
- The cookie MUST be a random value generated by the sender. Its
- purpose is to make it impossible for either side to fully
- determine the keys and the session identifier.
-
- kex_algorithms
- Key exchange algorithms were defined above. The first
- algorithm MUST be the preferred (and guessed) algorithm. If
- both sides make the same guess, that algorithm MUST be used.
- Otherwise, the following algorithm MUST be used to choose a key
- exchange method: iterate over client's kex algorithms, one at a
- time. Choose the first algorithm that satisfies the following
- conditions:
- + the server also supports the algorithm,
- + if the algorithm requires an encryption-capable host key,
- there is an encryption-capable algorithm on the server's
- server_host_key_algorithms that is also supported by the
- client, and
- + if the algorithm requires a signature-capable host key,
- there is a signature-capable algorithm on the server's
- server_host_key_algorithms that is also supported by the
- client.
- + If no algorithm satisfying all these conditions can be
- found, the connection fails, and both sides MUST disconnect.
-
-
-
-
-Ylonen & Moffat, Editor Expires March 31, 2004 [Page 14]
-
-Internet-Draft SSH Transport Layer Protocol Oct 2003
-
-
- server_host_key_algorithms
- List of the algorithms supported for the server host key. The
- server lists the algorithms for which it has host keys; the
- client lists the algorithms that it is willing to accept.
- (There MAY be multiple host keys for a host, possibly with
- different algorithms.)
-
- Some host keys may not support both signatures and encryption
- (this can be determined from the algorithm), and thus not all
- host keys are valid for all key exchange methods.
-
- Algorithm selection depends on whether the chosen key exchange
- algorithm requires a signature or encryption capable host key.
- It MUST be possible to determine this from the public key
- algorithm name. The first algorithm on the client's list that
- satisfies the requirements and is also supported by the server
- MUST be chosen. If there is no such algorithm, both sides MUST
- disconnect.
-
- encryption_algorithms
- Lists the acceptable symmetric encryption algorithms in order
- of preference. The chosen encryption algorithm to each
- direction MUST be the first algorithm on the client's list
- that is also on the server's list. If there is no such
- algorithm, both sides MUST disconnect.
-
- Note that "none" must be explicitly listed if it is to be
- acceptable. The defined algorithm names are listed in Section
- Section 5.3.
-
- mac_algorithms
- Lists the acceptable MAC algorithms in order of preference.
- The chosen MAC algorithm MUST be the first algorithm on the
- client's list that is also on the server's list. If there is
- no such algorithm, both sides MUST disconnect.
-
- Note that "none" must be explicitly listed if it is to be
- acceptable. The MAC algorithm names are listed in Section
- Figure 1.
-
- compression_algorithms
- Lists the acceptable compression algorithms in order of
- preference. The chosen compression algorithm MUST be the first
- algorithm on the client's list that is also on the server's
- list. If there is no such algorithm, both sides MUST
- disconnect.
-
-
-
-
-
-Ylonen & Moffat, Editor Expires March 31, 2004 [Page 15]
-
-Internet-Draft SSH Transport Layer Protocol Oct 2003
-
-
- Note that "none" must be explicitly listed if it is to be
- acceptable. The compression algorithm names are listed in
- Section Section 5.2.
-
- languages
- This is a comma-separated list of language tags in order of
- preference [RFC3066]. Both parties MAY ignore this list. If
- there are no language preferences, this list SHOULD be empty.
- Language tags SHOULD NOT be present unless they are known to be
- needed by the sending party.
-
- first_kex_packet_follows
- Indicates whether a guessed key exchange packet follows. If a
- guessed packet will be sent, this MUST be TRUE. If no guessed
- packet will be sent, this MUST be FALSE.
-
- After receiving the SSH_MSG_KEXINIT packet from the other side,
- each party will know whether their guess was right. If the
- other party's guess was wrong, and this field was TRUE, the
- next packet MUST be silently ignored, and both sides MUST then
- act as determined by the negotiated key exchange method. If
- the guess was right, key exchange MUST continue using the
- guessed packet.
-
- After the KEXINIT packet exchange, the key exchange algorithm is run.
- It may involve several packet exchanges, as specified by the key
- exchange method.
-
-6.2 Output from Key Exchange
-
- The key exchange produces two values: a shared secret K, and an
- exchange hash H. Encryption and authentication keys are derived from
- these. The exchange hash H from the first key exchange is
- additionally used as the session identifier, which is a unique
- identifier for this connection. It is used by authentication methods
- as a part of the data that is signed as a proof of possession of a
- private key. Once computed, the session identifier is not changed,
- even if keys are later re-exchanged.
-
-
- Each key exchange method specifies a hash function that is used in
- the key exchange. The same hash algorithm MUST be used in key
- derivation. Here, we'll call it HASH.
-
-
- Encryption keys MUST be computed as HASH of a known value and K as
- follows:
-
-
-
-
-Ylonen & Moffat, Editor Expires March 31, 2004 [Page 16]
-
-Internet-Draft SSH Transport Layer Protocol Oct 2003
-
-
- o Initial IV client to server: HASH(K || H || "A" || session_id)
- (Here K is encoded as mpint and "A" as byte and session_id as raw
- data."A" means the single character A, ASCII 65).
- o Initial IV server to client: HASH(K || H || "B" || session_id)
- o Encryption key client to server: HASH(K || H || "C" || session_id)
- o Encryption key server to client: HASH(K || H || "D" || session_id)
- o Integrity key client to server: HASH(K || H || "E" || session_id)
- o Integrity key server to client: HASH(K || H || "F" || session_id)
-
- Key data MUST be taken from the beginning of the hash output. 128
- bits (16 bytes) MUST be used for algorithms with variable-length
- keys. The only variable key length algorithm defined in this document
- is arcfour). For other algorithms, as many bytes as are needed are
- taken from the beginning of the hash value. If the key length needed
- is longer than the output of the HASH, the key is extended by
- computing HASH of the concatenation of K and H and the entire key so
- far, and appending the resulting bytes (as many as HASH generates) to
- the key. This process is repeated until enough key material is
- available; the key is taken from the beginning of this value. In
- other words:
-
- K1 = HASH(K || H || X || session_id) (X is e.g. "A")
- K2 = HASH(K || H || K1)
- K3 = HASH(K || H || K1 || K2)
- ...
- key = K1 || K2 || K3 || ...
-
- This process will lose entropy if the amount of entropy in K is
- larger than the internal state size of HASH.
-
-6.3 Taking Keys Into Use
-
- Key exchange ends by each side sending an SSH_MSG_NEWKEYS message.
- This message is sent with the old keys and algorithms. All messages
- sent after this message MUST use the new keys and algorithms.
-
-
- When this message is received, the new keys and algorithms MUST be
- taken into use for receiving.
-
-
- This message is the only valid message after key exchange, in
- addition to SSH_MSG_DEBUG, SSH_MSG_DISCONNECT and SSH_MSG_IGNORE
- messages. The purpose of this message is to ensure that a party is
- able to respond with a disconnect message that the other party can
- understand if something goes wrong with the key exchange.
- Implementations MUST NOT accept any other messages after key exchange
- before receiving SSH_MSG_NEWKEYS.
-
-
-
-Ylonen & Moffat, Editor Expires March 31, 2004 [Page 17]
-
-Internet-Draft SSH Transport Layer Protocol Oct 2003
-
-
- byte SSH_MSG_NEWKEYS
-
-
-7. Diffie-Hellman Key Exchange
-
- The Diffie-Hellman key exchange provides a shared secret that can not
- be determined by either party alone. The key exchange is combined
- with a signature with the host key to provide host authentication.
-
-
- In the following description (C is the client, S is the server; p is
- a large safe prime, g is a generator for a subgroup of GF(p), and q
- is the order of the subgroup; V_S is S's version string; V_C is C's
- version string; K_S is S's public host key; I_C is C's KEXINIT
- message and I_S S's KEXINIT message which have been exchanged before
- this part begins):
-
-
- 1. C generates a random number x (1 < x < q) and computes e = g^x
- mod p. C sends "e" to S.
-
- 2. S generates a random number y (0 < y < q) and computes f = g^y
- mod p. S receives "e". It computes K = e^y mod p, H = hash(V_C
- || V_S || I_C || I_S || K_S || e || f || K) (these elements are
- encoded according to their types; see below), and signature s on
- H with its private host key. S sends "K_S || f || s" to C. The
- signing operation may involve a second hashing operation.
-
- 3. C verifies that K_S really is the host key for S (e.g. using
- certificates or a local database). C is also allowed to accept
- the key without verification; however, doing so will render the
- protocol insecure against active attacks (but may be desirable
- for practical reasons in the short term in many environments). C
- then computes K = f^x mod p, H = hash(V_C || V_S || I_C || I_S ||
- K_S || e || f || K), and verifies the signature s on H.
-
- Either side MUST NOT send or accept e or f values that are not in the
- range [1, p-1]. If this condition is violated, the key exchange
- fails.
-
-
- This is implemented with the following messages. The hash algorithm
- for computing the exchange hash is defined by the method name, and is
- called HASH. The public key algorithm for signing is negotiated with
- the KEXINIT messages.
-
- First, the client sends the following:
-
-
-
-
-Ylonen & Moffat, Editor Expires March 31, 2004 [Page 18]
-
-Internet-Draft SSH Transport Layer Protocol Oct 2003
-
-
- byte SSH_MSG_KEXDH_INIT
- mpint e
-
-
- The server responds with the following:
-
- byte SSH_MSG_KEXDH_REPLY
- string server public host key and certificates (K_S)
- mpint f
- string signature of H
-
- The hash H is computed as the HASH hash of the concatenation of the
- following:
-
- string V_C, the client's version string (CR and NL excluded)
- string V_S, the server's version string (CR and NL excluded)
- string I_C, the payload of the client's SSH_MSG_KEXINIT
- string I_S, the payload of the server's SSH_MSG_KEXINIT
- string K_S, the host key
- mpint e, exchange value sent by the client
- mpint f, exchange value sent by the server
- mpint K, the shared secret
-
- This value is called the exchange hash, and it is used to
- authenticate the key exchange. The exchange hash SHOULD be kept
- secret.
-
-
- The signature algorithm MUST be applied over H, not the original
- data. Most signature algorithms include hashing and additional
- padding. For example, "ssh-dss" specifies SHA-1 hashing; in that
- case, the data is first hashed with HASH to compute H, and H is then
- hashed with SHA-1 as part of the signing operation.
-
-7.1 diffie-hellman-group1-sha1
-
- The "diffie-hellman-group1-sha1" method specifies Diffie-Hellman key
- exchange with SHA-1 as HASH, and Oakley group 14 [RFC3526] (2048-bit
- MODP Group). It is included below in hexadecimal and decimal.
-
- The prime p is equal to 2^1024 - 2^960 - 1 + 2^64 * floor( 2^894 Pi +
- 129093 ). Its hexadecimal value is:
-
- FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1
- 29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD
- EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245
- E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED
- EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE65381
-
-
-
-Ylonen & Moffat, Editor Expires March 31, 2004 [Page 19]
-
-Internet-Draft SSH Transport Layer Protocol Oct 2003
-
-
- FFFFFFFF FFFFFFFF.
-
- In decimal, this value is:
-
- 179769313486231590770839156793787453197860296048756011706444
- 423684197180216158519368947833795864925541502180565485980503
- 646440548199239100050792877003355816639229553136239076508735
- 759914822574862575007425302077447712589550957937778424442426
- 617334727629299387668709205606050270810842907692932019128194
- 467627007.
-
- The generator used with this prime is g = 2. The group order q is (p
- - 1) / 2.
-
-8. Key Re-Exchange
-
- Key re-exchange is started by sending an SSH_MSG_KEXINIT packet when
- not already doing a key exchange (as described in Section Section
- 6.1). When this message is received, a party MUST respond with its
- own SSH_MSG_KEXINIT message except when the received SSH_MSG_KEXINIT
- already was a reply. Either party MAY initiate the re-exchange, but
- roles MUST NOT be changed (i.e., the server remains the server, and
- the client remains the client).
-
-
- Key re-exchange is performed using whatever encryption was in effect
- when the exchange was started. Encryption, compression, and MAC
- methods are not changed before a new SSH_MSG_NEWKEYS is sent after
- the key exchange (as in the initial key exchange). Re-exchange is
- processed identically to the initial key exchange, except for the
- session identifier that will remain unchanged. It is permissible to
- change some or all of the algorithms during the re-exchange. Host
- keys can also change. All keys and initialization vectors are
- recomputed after the exchange. Compression and encryption contexts
- are reset.
-
-
- It is recommended that the keys are changed after each gigabyte of
- transmitted data or after each hour of connection time, whichever
- comes sooner. However, since the re-exchange is a public key
- operation, it requires a fair amount of processing power and should
- not be performed too often.
-
-
- More application data may be sent after the SSH_MSG_NEWKEYS packet
- has been sent; key exchange does not affect the protocols that lie
- above the SSH transport layer.
-
-
-
-
-Ylonen & Moffat, Editor Expires March 31, 2004 [Page 20]
-
-Internet-Draft SSH Transport Layer Protocol Oct 2003
-
-
-9. Service Request
-
- After the key exchange, the client requests a service. The service is
- identified by a name. The format of names and procedures for defining
- new names are defined in [SSH-ARCH].
-
-
- Currently, the following names have been reserved:
-
- ssh-userauth
- ssh-connection
-
- Similar local naming policy is applied to the service names, as is
- applied to the algorithm names; a local service should use the
- "servicename@domain" syntax.
-
- byte SSH_MSG_SERVICE_REQUEST
- string service name
-
- If the server rejects the service request, it SHOULD send an
- appropriate SSH_MSG_DISCONNECT message and MUST disconnect.
-
-
- When the service starts, it may have access to the session identifier
- generated during the key exchange.
-
-
- If the server supports the service (and permits the client to use
- it), it MUST respond with the following:
-
- byte SSH_MSG_SERVICE_ACCEPT
- string service name
-
- Message numbers used by services should be in the area reserved for
- them (see Section 6 in [SSH-ARCH]). The transport level will
- continue to process its own messages.
-
-
- Note that after a key exchange with implicit server authentication,
- the client MUST wait for response to its service request message
- before sending any further data.
-
-10. Additional Messages
-
- Either party may send any of the following messages at any time.
-
-
-
-
-
-
-Ylonen & Moffat, Editor Expires March 31, 2004 [Page 21]
-
-Internet-Draft SSH Transport Layer Protocol Oct 2003
-
-
-10.1 Disconnection Message
-
- byte SSH_MSG_DISCONNECT
- uint32 reason code
- string description [RFC2279]
- string language tag [RFC3066]
-
- This message causes immediate termination of the connection. All
- implementations MUST be able to process this message; they SHOULD be
- able to send this message.
-
- The sender MUST NOT send or receive any data after this message, and
- the recipient MUST NOT accept any data after receiving this message.
- The description field gives a more specific explanation in a
- human-readable form. The error code gives the reason in a more
- machine-readable format (suitable for localization), and can have the
- following values:
-
- #define SSH_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT 1
- #define SSH_DISCONNECT_PROTOCOL_ERROR 2
- #define SSH_DISCONNECT_KEY_EXCHANGE_FAILED 3
- #define SSH_DISCONNECT_RESERVED 4
- #define SSH_DISCONNECT_MAC_ERROR 5
- #define SSH_DISCONNECT_COMPRESSION_ERROR 6
- #define SSH_DISCONNECT_SERVICE_NOT_AVAILABLE 7
- #define SSH_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED 8
- #define SSH_DISCONNECT_HOST_KEY_NOT_VERIFIABLE 9
- #define SSH_DISCONNECT_CONNECTION_LOST 10
- #define SSH_DISCONNECT_BY_APPLICATION 11
- #define SSH_DISCONNECT_TOO_MANY_CONNECTIONS 12
- #define SSH_DISCONNECT_AUTH_CANCELLED_BY_USER 13
- #define SSH_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE 14
- #define SSH_DISCONNECT_ILLEGAL_USER_NAME 15
-
- If the description string is displayed, control character filtering
- discussed in [SSH-ARCH] should be used to avoid attacks by sending
- terminal control characters.
-
-10.2 Ignored Data Message
-
- byte SSH_MSG_IGNORE
- string data
-
- All implementations MUST understand (and ignore) this message at any
- time (after receiving the protocol version). No implementation is
- required to send them. This message can be used as an additional
- protection measure against advanced traffic analysis techniques.
-
-
-
-
-Ylonen & Moffat, Editor Expires March 31, 2004 [Page 22]
-
-Internet-Draft SSH Transport Layer Protocol Oct 2003
-
-
-10.3 Debug Message
-
- byte SSH_MSG_DEBUG
- boolean always_display
- string message [RFC2279]
- string language tag [RFC3066]
-
- All implementations MUST understand this message, but they are
- allowed to ignore it. This message is used to pass the other side
- information that may help debugging. If always_display is TRUE, the
- message SHOULD be displayed. Otherwise, it SHOULD NOT be displayed
- unless debugging information has been explicitly requested by the
- user.
-
-
- The message doesn't need to contain a newline. It is, however,
- allowed to consist of multiple lines separated by CRLF (Carriage
- Return - Line Feed) pairs.
-
-
- If the message string is displayed, terminal control character
- filtering discussed in [SSH-ARCH] should be used to avoid attacks by
- sending terminal control characters.
-
-10.4 Reserved Messages
-
- An implementation MUST respond to all unrecognized messages with an
- SSH_MSG_UNIMPLEMENTED message in the order in which the messages were
- received. Such messages MUST be otherwise ignored. Later protocol
- versions may define other meanings for these message types.
-
- byte SSH_MSG_UNIMPLEMENTED
- uint32 packet sequence number of rejected message
-
-
-11. Summary of Message Numbers
-
- The following message numbers have been defined in this protocol:
-
- #define SSH_MSG_DISCONNECT 1
- #define SSH_MSG_IGNORE 2
- #define SSH_MSG_UNIMPLEMENTED 3
- #define SSH_MSG_DEBUG 4
- #define SSH_MSG_SERVICE_REQUEST 5
- #define SSH_MSG_SERVICE_ACCEPT 6
-
- #define SSH_MSG_KEXINIT 20
- #define SSH_MSG_NEWKEYS 21
-
-
-
-Ylonen & Moffat, Editor Expires March 31, 2004 [Page 23]
-
-Internet-Draft SSH Transport Layer Protocol Oct 2003
-
-
- /* Numbers 30-49 used for kex packets.
- Different kex methods may reuse message numbers in
- this range. */
-
- #define SSH_MSG_KEXDH_INIT 30
- #define SSH_MSG_KEXDH_REPLY 31
-
-
-12. IANA Considerations
-
- This document is part of a set, the IANA considerations for the SSH
- protocol as defined in [SSH-ARCH], [SSH-TRANS], [SSH-USERAUTH],
- [SSH-CONNECT] are detailed in [SSH-NUMBERS].
-
-13. Security Considerations
-
- This protocol provides a secure encrypted channel over an insecure
- network. It performs server host authentication, key exchange,
- encryption, and integrity protection. It also derives a unique
- session id that may be used by higher-level protocols.
-
- Full security considerations for this protocol are provided in
- Section 8 of [SSH-ARCH]
-
-14. Intellectual Property
-
- The IETF takes no position regarding the validity or scope of any
- intellectual property or other rights that might be claimed to
- pertain to the implementation or use of the technology described in
- this document or the extent to which any license under such rights
- might or might not be available; neither does it represent that it
- has made any effort to identify any such rights. Information on the
- IETF's procedures with respect to rights in standards-track and
- standards-related documentation can be found in BCP-11. Copies of
- claims of rights made available for publication and any assurances of
- licenses to be made available, or the result of an attempt made to
- obtain a general license or permission for the use of such
- proprietary rights by implementers or users of this specification can
- be obtained from the IETF Secretariat.
-
- The IETF has been notified of intellectual property rights claimed in
- regard to some or all of the specification contained in this
- document. For more information consult the online list of claimed
- rights.
-
-15. Additional Information
-
- The current document editor is: [email protected]. Comments on
-
-
-
-Ylonen & Moffat, Editor Expires March 31, 2004 [Page 24]
-
-Internet-Draft SSH Transport Layer Protocol Oct 2003
-
-
- this internet draft should be sent to the IETF SECSH working group,
- details at: http://ietf.org/html.charters/secsh-charter.html
-
-Normative
-
- [SSH-ARCH]
- Ylonen, T., "SSH Protocol Architecture", I-D
- draft-ietf-architecture-15.txt, Oct 2003.
-
- [SSH-TRANS]
- Ylonen, T., "SSH Transport Layer Protocol", I-D
- draft-ietf-transport-17.txt, Oct 2003.
-
- [SSH-USERAUTH]
- Ylonen, T., "SSH Authentication Protocol", I-D
- draft-ietf-userauth-18.txt, Oct 2003.
-
- [SSH-CONNECT]
- Ylonen, T., "SSH Connection Protocol", I-D
- draft-ietf-connect-18.txt, Oct 2003.
-
- [SSH-NUMBERS]
- Lehtinen, S. and D. Moffat, "SSH Protocol Assigned
- Numbers", I-D draft-ietf-secsh-assignednumbers-05.txt, Oct
- 2003.
-
- [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
- Requirement Levels", BCP 14, RFC 2119, March 1997.
-
-Informative
-
- [FIPS-186]
- Federal Information Processing Standards Publication,
- "FIPS PUB 186, Digital Signature Standard", May 1994.
-
- [FIPS-197]
- NIST, "FIPS PUB 197 Advanced Encryption Standard (AES)",
- November 2001.
-
- [FIPS-46-3]
- U.S. Dept. of Commerce, "FIPS PUB 46-3, Data Encryption
- Standard (DES)", October 1999.
-
- [RFC2459] Housley, R., Ford, W., Polk, T. and D. Solo, "Internet
- X.509 Public Key Infrastructure Certificate and CRL
- Profile", RFC 2459, January 1999.
-
- [RFC1034] Mockapetris, P., "Domain names - concepts and facilities",
-
-
-
-Ylonen & Moffat, Editor Expires March 31, 2004 [Page 25]
-
-Internet-Draft SSH Transport Layer Protocol Oct 2003
-
-
- STD 13, RFC 1034, November 1987.
-
- [RFC3066] Alvestrand, H., "Tags for the Identification of
- Languages", BCP 47, RFC 3066, January 2001.
-
- [RFC1950] Deutsch, L. and J-L. Gailly, "ZLIB Compressed Data Format
- Specification version 3.3", RFC 1950, May 1996.
-
- [RFC1951] Deutsch, P., "DEFLATE Compressed Data Format Specification
- version 1.3", RFC 1951, May 1996.
-
- [RFC2279] Yergeau, F., "UTF-8, a transformation format of ISO
- 10646", RFC 2279, January 1998.
-
- [RFC2104] Krawczyk, H., Bellare, M. and R. Canetti, "HMAC:
- Keyed-Hashing for Message Authentication", RFC 2104,
- February 1997.
-
- [RFC2144] Adams, C., "The CAST-128 Encryption Algorithm", RFC 2144,
- May 1997.
-
- [RFC2440] Callas, J., Donnerhacke, L., Finney, H. and R. Thayer,
- "OpenPGP Message Format", RFC 2440, November 1998.
-
- [RFC2693] Ellison, C., Frantz, B., Lampson, B., Rivest, R., Thomas,
- B. and T. Ylonen, "SPKI Certificate Theory", RFC 2693,
- September 1999.
-
- [RFC3526] Kivinen, T. and M. Kojo, "More Modular Exponential (MODP)
- Diffie-Hellman groups for Internet Key Exchange (IKE)",
- RFC 3526, May 2003.
-
- [SCHNEIER]
- Schneier, B., "Applied Cryptography Second Edition:
- protocols algorithms and source in code in C", 1996.
-
- [TWOFISH] Schneier, B., "The Twofish Encryptions Algorithm: A
- 128-Bit Block Cipher, 1st Edition", March 1999.
-
-
-
-
-
-
-
-
-
-
-
-
-
-Ylonen & Moffat, Editor Expires March 31, 2004 [Page 26]
-
-Internet-Draft SSH Transport Layer Protocol Oct 2003
-
-
-Authors' Addresses
-
- Tatu Ylonen
- SSH Communications Security Corp
- Fredrikinkatu 42
- HELSINKI FIN-00100
- Finland
-
-
-
- Darren J. Moffat (editor)
- Sun Microsystems, Inc
- 17 Network Circle
- Menlo Park 95025
- USA
-
-
-Appendix A. Contibutors
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Ylonen & Moffat, Editor Expires March 31, 2004 [Page 27]
-
-Internet-Draft SSH Transport Layer Protocol Oct 2003
-
-
-Intellectual Property Statement
-
- The IETF takes no position regarding the validity or scope of any
- intellectual property or other rights that might be claimed to
- pertain to the implementation or use of the technology described in
- this document or the extent to which any license under such rights
- might or might not be available; neither does it represent that it
- has made any effort to identify any such rights. Information on the
- IETF's procedures with respect to rights in standards-track and
- standards-related documentation can be found in BCP-11. Copies of
- claims of rights made available for publication and any assurances of
- licenses to be made available, or the result of an attempt made to
- obtain a general license or permission for the use of such
- proprietary rights by implementors or users of this specification can
- be obtained from the IETF Secretariat.
-
- The IETF invites any interested party to bring to its attention any
- copyrights, patents or patent applications, or other proprietary
- rights which may cover technology that may be required to practice
- this standard. Please address the information to the IETF Executive
- Director.
-
- The IETF has been notified of intellectual property rights claimed in
- regard to some or all of the specification contained in this
- document. For more information consult the online list of claimed
- rights.
-
-
-Full Copyright Statement
-
- Copyright (C) The Internet Society (2003). All Rights Reserved.
-
- This document and translations of it may be copied and furnished to
- others, and derivative works that comment on or otherwise explain it
- or assist in its implementation may be prepared, copied, published
- and distributed, in whole or in part, without restriction of any
- kind, provided that the above copyright notice and this paragraph are
- included on all such copies and derivative works. However, this
- document itself may not be modified in any way, such as by removing
- the copyright notice or references to the Internet Society or other
- Internet organizations, except as needed for the purpose of
- developing Internet standards in which case the procedures for
- copyrights defined in the Internet Standards process must be
- followed, or as required to translate it into languages other than
- English.
-
- The limited permissions granted above are perpetual and will not be
- revoked by the Internet Society or its successors or assignees.
-
-
-
-Ylonen & Moffat, Editor Expires March 31, 2004 [Page 28]
-
-Internet-Draft SSH Transport Layer Protocol Oct 2003
-
-
- This document and the information contained herein is provided on an
- "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
- TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
- BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
- HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
- MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
-
-
-Acknowledgment
-
- Funding for the RFC Editor function is currently provided by the
- Internet Society.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Ylonen & Moffat, Editor Expires March 31, 2004 [Page 29] \ No newline at end of file
diff --git a/lib/ssh/doc/standard/draft-ietf-secsh-userauth-18.2.ps b/lib/ssh/doc/standard/draft-ietf-secsh-userauth-18.2.ps
deleted file mode 100644
index be5799dbce..0000000000
--- a/lib/ssh/doc/standard/draft-ietf-secsh-userauth-18.2.ps
+++ /dev/null
@@ -1,1881 +0,0 @@
-%!PS-Adobe-3.0
-%%BoundingBox: 75 0 595 747
-%%Title: Enscript Output
-%%For: Magnus Thoang
-%%Creator: GNU enscript 1.6.1
-%%CreationDate: Fri Oct 31 13:35:32 2003
-%%Orientation: Portrait
-%%Pages: 8 0
-%%DocumentMedia: A4 595 842 0 () ()
-%%DocumentNeededResources: (atend)
-%%EndComments
-%%BeginProlog
-%%BeginProcSet: PStoPS 1 15
-userdict begin
-[/showpage/erasepage/copypage]{dup where{pop dup load
- type/operatortype eq{1 array cvx dup 0 3 index cvx put
- bind def}{pop}ifelse}{pop}ifelse}forall
-[/letter/legal/executivepage/a4/a4small/b5/com10envelope
- /monarchenvelope/c5envelope/dlenvelope/lettersmall/note
- /folio/quarto/a5]{dup where{dup wcheck{exch{}put}
- {pop{}def}ifelse}{pop}ifelse}forall
-/setpagedevice {pop}bind 1 index where{dup wcheck{3 1 roll put}
- {pop def}ifelse}{def}ifelse
-/PStoPSmatrix matrix currentmatrix def
-/PStoPSxform matrix def/PStoPSclip{clippath}def
-/defaultmatrix{PStoPSmatrix exch PStoPSxform exch concatmatrix}bind def
-/initmatrix{matrix defaultmatrix setmatrix}bind def
-/initclip[{matrix currentmatrix PStoPSmatrix setmatrix
- [{currentpoint}stopped{$error/newerror false put{newpath}}
- {/newpath cvx 3 1 roll/moveto cvx 4 array astore cvx}ifelse]
- {[/newpath cvx{/moveto cvx}{/lineto cvx}
- {/curveto cvx}{/closepath cvx}pathforall]cvx exch pop}
- stopped{$error/errorname get/invalidaccess eq{cleartomark
- $error/newerror false put cvx exec}{stop}ifelse}if}bind aload pop
- /initclip dup load dup type dup/operatortype eq{pop exch pop}
- {dup/arraytype eq exch/packedarraytype eq or
- {dup xcheck{exch pop aload pop}{pop cvx}ifelse}
- {pop cvx}ifelse}ifelse
- {newpath PStoPSclip clip newpath exec setmatrix} bind aload pop]cvx def
-/initgraphics{initmatrix newpath initclip 1 setlinewidth
- 0 setlinecap 0 setlinejoin []0 setdash 0 setgray
- 10 setmiterlimit}bind def
-end
-%%EndProcSet
-%%BeginResource: procset Enscript-Prolog 1.6 1
-%
-% Procedures.
-%
-
-/_S { % save current state
- /_s save def
-} def
-/_R { % restore from saved state
- _s restore
-} def
-
-/S { % showpage protecting gstate
- gsave
- showpage
- grestore
-} bind def
-
-/MF { % fontname newfontname -> - make a new encoded font
- /newfontname exch def
- /fontname exch def
-
- /fontdict fontname findfont def
- /newfont fontdict maxlength dict def
-
- fontdict {
- exch
- dup /FID eq {
- % skip FID pair
- pop pop
- } {
- % copy to the new font dictionary
- exch newfont 3 1 roll put
- } ifelse
- } forall
-
- newfont /FontName newfontname put
-
- % insert only valid encoding vectors
- encoding_vector length 256 eq {
- newfont /Encoding encoding_vector put
- } if
-
- newfontname newfont definefont pop
-} def
-
-/SF { % fontname width height -> - set a new font
- /height exch def
- /width exch def
-
- findfont
- [width 0 0 height 0 0] makefont setfont
-} def
-
-/SUF { % fontname width height -> - set a new user font
- /height exch def
- /width exch def
-
- /F-gs-user-font MF
- /F-gs-user-font width height SF
-} def
-
-/M {moveto} bind def
-/s {show} bind def
-
-/Box { % x y w h -> - define box path
- /d_h exch def /d_w exch def /d_y exch def /d_x exch def
- d_x d_y moveto
- d_w 0 rlineto
- 0 d_h rlineto
- d_w neg 0 rlineto
- closepath
-} def
-
-/bgs { % x y height blskip gray str -> - show string with bg color
- /str exch def
- /gray exch def
- /blskip exch def
- /height exch def
- /y exch def
- /x exch def
-
- gsave
- x y blskip sub str stringwidth pop height Box
- gray setgray
- fill
- grestore
- x y M str s
-} def
-
-% Highlight bars.
-/highlight_bars { % nlines lineheight output_y_margin gray -> -
- gsave
- setgray
- /ymarg exch def
- /lineheight exch def
- /nlines exch def
-
- % This 2 is just a magic number to sync highlight lines to text.
- 0 d_header_y ymarg sub 2 sub translate
-
- /cw d_output_w cols div def
- /nrows d_output_h ymarg 2 mul sub lineheight div cvi def
-
- % for each column
- 0 1 cols 1 sub {
- cw mul /xp exch def
-
- % for each rows
- 0 1 nrows 1 sub {
- /rn exch def
- rn lineheight mul neg /yp exch def
- rn nlines idiv 2 mod 0 eq {
- % Draw highlight bar. 4 is just a magic indentation.
- xp 4 add yp cw 8 sub lineheight neg Box fill
- } if
- } for
- } for
-
- grestore
-} def
-
-% Line highlight bar.
-/line_highlight { % x y width height gray -> -
- gsave
- /gray exch def
- Box gray setgray fill
- grestore
-} def
-
-% Column separator lines.
-/column_lines {
- gsave
- .1 setlinewidth
- 0 d_footer_h translate
- /cw d_output_w cols div def
- 1 1 cols 1 sub {
- cw mul 0 moveto
- 0 d_output_h rlineto stroke
- } for
- grestore
-} def
-
-% Column borders.
-/column_borders {
- gsave
- .1 setlinewidth
- 0 d_footer_h moveto
- 0 d_output_h rlineto
- d_output_w 0 rlineto
- 0 d_output_h neg rlineto
- closepath stroke
- grestore
-} def
-
-% Do the actual underlay drawing
-/draw_underlay {
- ul_style 0 eq {
- ul_str true charpath stroke
- } {
- ul_str show
- } ifelse
-} def
-
-% Underlay
-/underlay { % - -> -
- gsave
- 0 d_page_h translate
- d_page_h neg d_page_w atan rotate
-
- ul_gray setgray
- ul_font setfont
- /dw d_page_h dup mul d_page_w dup mul add sqrt def
- ul_str stringwidth pop dw exch sub 2 div ul_h_ptsize -2 div moveto
- draw_underlay
- grestore
-} def
-
-/user_underlay { % - -> -
- gsave
- ul_x ul_y translate
- ul_angle rotate
- ul_gray setgray
- ul_font setfont
- 0 0 ul_h_ptsize 2 div sub moveto
- draw_underlay
- grestore
-} def
-
-% Page prefeed
-/page_prefeed { % bool -> -
- statusdict /prefeed known {
- statusdict exch /prefeed exch put
- } {
- pop
- } ifelse
-} def
-
-% Wrapped line markers
-/wrapped_line_mark { % x y charwith charheight type -> -
- /type exch def
- /h exch def
- /w exch def
- /y exch def
- /x exch def
-
- type 2 eq {
- % Black boxes (like TeX does)
- gsave
- 0 setlinewidth
- x w 4 div add y M
- 0 h rlineto w 2 div 0 rlineto 0 h neg rlineto
- closepath fill
- grestore
- } {
- type 3 eq {
- % Small arrows
- gsave
- .2 setlinewidth
- x w 2 div add y h 2 div add M
- w 4 div 0 rlineto
- x w 4 div add y lineto stroke
-
- x w 4 div add w 8 div add y h 4 div add M
- x w 4 div add y lineto
- w 4 div h 8 div rlineto stroke
- grestore
- } {
- % do nothing
- } ifelse
- } ifelse
-} def
-
-% EPSF import.
-
-/BeginEPSF {
- /b4_Inc_state save def % Save state for cleanup
- /dict_count countdictstack def % Count objects on dict stack
- /op_count count 1 sub def % Count objects on operand stack
- userdict begin
- /showpage { } def
- 0 setgray 0 setlinecap
- 1 setlinewidth 0 setlinejoin
- 10 setmiterlimit [ ] 0 setdash newpath
- /languagelevel where {
- pop languagelevel
- 1 ne {
- false setstrokeadjust false setoverprint
- } if
- } if
-} bind def
-
-/EndEPSF {
- count op_count sub { pos } repeat % Clean up stacks
- countdictstack dict_count sub { end } repeat
- b4_Inc_state restore
-} bind def
-
-% Check PostScript language level.
-/languagelevel where {
- pop /gs_languagelevel languagelevel def
-} {
- /gs_languagelevel 1 def
-} ifelse
-%%EndResource
-%%BeginResource: procset Enscript-Encoding-88591 1.6 1
-/encoding_vector [
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/space /exclam /quotedbl /numbersign
-/dollar /percent /ampersand /quoteright
-/parenleft /parenright /asterisk /plus
-/comma /hyphen /period /slash
-/zero /one /two /three
-/four /five /six /seven
-/eight /nine /colon /semicolon
-/less /equal /greater /question
-/at /A /B /C
-/D /E /F /G
-/H /I /J /K
-/L /M /N /O
-/P /Q /R /S
-/T /U /V /W
-/X /Y /Z /bracketleft
-/backslash /bracketright /asciicircum /underscore
-/quoteleft /a /b /c
-/d /e /f /g
-/h /i /j /k
-/l /m /n /o
-/p /q /r /s
-/t /u /v /w
-/x /y /z /braceleft
-/bar /braceright /tilde /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef
-/space /exclamdown /cent /sterling
-/currency /yen /brokenbar /section
-/dieresis /copyright /ordfeminine /guillemotleft
-/logicalnot /hyphen /registered /macron
-/degree /plusminus /twosuperior /threesuperior
-/acute /mu /paragraph /bullet
-/cedilla /onesuperior /ordmasculine /guillemotright
-/onequarter /onehalf /threequarters /questiondown
-/Agrave /Aacute /Acircumflex /Atilde
-/Adieresis /Aring /AE /Ccedilla
-/Egrave /Eacute /Ecircumflex /Edieresis
-/Igrave /Iacute /Icircumflex /Idieresis
-/Eth /Ntilde /Ograve /Oacute
-/Ocircumflex /Otilde /Odieresis /multiply
-/Oslash /Ugrave /Uacute /Ucircumflex
-/Udieresis /Yacute /Thorn /germandbls
-/agrave /aacute /acircumflex /atilde
-/adieresis /aring /ae /ccedilla
-/egrave /eacute /ecircumflex /edieresis
-/igrave /iacute /icircumflex /idieresis
-/eth /ntilde /ograve /oacute
-/ocircumflex /otilde /odieresis /divide
-/oslash /ugrave /uacute /ucircumflex
-/udieresis /yacute /thorn /ydieresis
-] def
-%%EndResource
-%%EndProlog
-%%BeginSetup
-%%IncludeResource: font Courier-Bold
-%%IncludeResource: font Courier
-/HFpt_w 10 def
-/HFpt_h 10 def
-/Courier-Bold /HF-gs-font MF
-/HF /HF-gs-font findfont [HFpt_w 0 0 HFpt_h 0 0] makefont def
-/Courier /F-gs-font MF
-/F-gs-font 10 10 SF
-/#copies 1 def
-/d_page_w 520 def
-/d_page_h 747 def
-/d_header_x 0 def
-/d_header_y 747 def
-/d_header_w 520 def
-/d_header_h 0 def
-/d_footer_x 0 def
-/d_footer_y 0 def
-/d_footer_w 520 def
-/d_footer_h 0 def
-/d_output_w 520 def
-/d_output_h 747 def
-/cols 1 def
-userdict/PStoPSxform PStoPSmatrix matrix currentmatrix
- matrix invertmatrix matrix concatmatrix
- matrix invertmatrix put
-%%EndSetup
-%%Page: (0,1) 1
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 1 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 701 M
-(Network Working Group T. Ylonen) s
-5 690 M
-(Internet-Draft SSH Communications Security Corp) s
-5 679 M
-(Expires: March 2, 2003 D. Moffat, Ed.) s
-5 668 M
-( Sun Microsystems, Inc) s
-5 657 M
-( September 2002) s
-5 624 M
-( SSH Authentication Protocol) s
-5 613 M
-( draft-ietf-secsh-userauth-18.txt) s
-5 591 M
-(Status of this Memo) s
-5 569 M
-( This document is an Internet-Draft and is in full conformance with) s
-5 558 M
-( all provisions of Section 10 of RFC2026.) s
-5 536 M
-( Internet-Drafts are working documents of the Internet Engineering) s
-5 525 M
-( Task Force \(IETF\), its areas, and its working groups. Note that other) s
-5 514 M
-( groups may also distribute working documents as Internet-Drafts.) s
-5 492 M
-( Internet-Drafts are draft documents valid for a maximum of six months) s
-5 481 M
-( and may be updated, replaced, or obsoleted by other documents at any) s
-5 470 M
-( time. It is inappropriate to use Internet-Drafts as reference) s
-5 459 M
-( material or to cite them other than as "work in progress.") s
-5 437 M
-( The list of current Internet-Drafts can be accessed at http://) s
-5 426 M
-( www.ietf.org/ietf/1id-abstracts.txt.) s
-5 404 M
-( The list of Internet-Draft Shadow Directories can be accessed at) s
-5 393 M
-( http://www.ietf.org/shadow.html.) s
-5 371 M
-( This Internet-Draft will expire on March 2, 2003.) s
-5 349 M
-(Copyright Notice) s
-5 327 M
-( Copyright \(C\) The Internet Society \(2002\). All Rights Reserved.) s
-5 305 M
-(Abstract) s
-5 283 M
-( SSH is a protocol for secure remote login and other secure network) s
-5 272 M
-( services over an insecure network. This document describes the SSH) s
-5 261 M
-( authentication protocol framework and public key, password, and) s
-5 250 M
-( host-based client authentication methods. Additional authentication) s
-5 239 M
-( methods are described in separate documents. The SSH authentication) s
-5 228 M
-( protocol runs on top of the SSH transport layer protocol and provides) s
-5 217 M
-( a single authenticated tunnel for the SSH connection protocol.) s
-5 129 M
-(Ylonen & Moffat Expires March 2, 2003 [Page 1]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 2 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Authentication Protocol September 2002) s
-5 690 M
-(Table of Contents) s
-5 668 M
-( 1. Contributors . . . . . . . . . . . . . . . . . . . . . . . . 3) s
-5 657 M
-( 2. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3) s
-5 646 M
-( 3. Conventions Used in This Document . . . . . . . . . . . . . 3) s
-5 635 M
-( 3.1 The Authentication Protocol Framework . . . . . . . . . . . 3) s
-5 624 M
-( 3.1.1 Authentication Requests . . . . . . . . . . . . . . . . . . 4) s
-5 613 M
-( 3.1.2 Responses to Authentication Requests . . . . . . . . . . . . 5) s
-5 602 M
-( 3.1.3 The "none" Authentication Request . . . . . . . . . . . . . 6) s
-5 591 M
-( 3.1.4 Completion of User Authentication . . . . . . . . . . . . . 6) s
-5 580 M
-( 3.1.5 Banner Message . . . . . . . . . . . . . . . . . . . . . . . 7) s
-5 569 M
-( 3.2 Authentication Protocol Message Numbers . . . . . . . . . . 7) s
-5 558 M
-( 3.3 Public Key Authentication Method: publickey . . . . . . . . 8) s
-5 547 M
-( 3.4 Password Authentication Method: password . . . . . . . . . . 10) s
-5 536 M
-( 3.5 Host-Based Authentication: hostbased . . . . . . . . . . . . 11) s
-5 525 M
-( 4. Security Considerations . . . . . . . . . . . . . . . . . . 12) s
-5 514 M
-( Normative . . . . . . . . . . . . . . . . . . . . . . . . . 13) s
-5 503 M
-( Informative . . . . . . . . . . . . . . . . . . . . . . . . 13) s
-5 492 M
-( Authors' Addresses . . . . . . . . . . . . . . . . . . . . . 14) s
-5 481 M
-( Intellectual Property and Copyright Statements . . . . . . . 15) s
-5 129 M
-(Ylonen & Moffat Expires March 2, 2003 [Page 2]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (2,3) 2
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 3 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Authentication Protocol September 2002) s
-5 690 M
-(1. Contributors) s
-5 668 M
-( The major original contributors of this document were: Tatu Ylonen,) s
-5 657 M
-( Tero Kivinen, Timo J. Rinne, Sami Lehtinen \(all of SSH Communications) s
-5 646 M
-( Security Corp\), and Markku-Juhani O. Saarinen \(University of) s
-5 635 M
-( Jyvaskyla\)) s
-5 613 M
-( The document editor is: [email protected]. Comments on this) s
-5 602 M
-( internet draft should be sent to the IETF SECSH working group,) s
-5 591 M
-( details at: http://ietf.org/html.charters/secsh-charter.html) s
-5 569 M
-(2. Introduction) s
-5 547 M
-( The SSH authentication protocol is a general-purpose user) s
-5 536 M
-( authentication protocol. It is intended to be run over the SSH) s
-5 525 M
-( transport layer protocol [SSH-TRANS]. This protocol assumes that the) s
-5 514 M
-( underlying protocols provide integrity and confidentiality) s
-5 503 M
-( protection.) s
-5 481 M
-( This document should be read only after reading the SSH architecture) s
-5 470 M
-( document [SSH-ARCH]. This document freely uses terminology and) s
-5 459 M
-( notation from the architecture document without reference or further) s
-5 448 M
-( explanation.) s
-5 426 M
-( The service name for this protocol is "ssh-userauth".) s
-5 404 M
-( When this protocol starts, it receives the session identifier from) s
-5 393 M
-( the lower-level protocol \(this is the exchange hash H from the first) s
-5 382 M
-( key exchange\). The session identifier uniquely identifies this) s
-5 371 M
-( session and is suitable for signing in order to prove ownership of a) s
-5 360 M
-( private key. This protocol also needs to know whether the lower-level) s
-5 349 M
-( protocol provides confidentiality protection.) s
-5 327 M
-(3. Conventions Used in This Document) s
-5 305 M
-( The keywords "MUST", "MUST NOT", "REQUIRED", "SHOULD", "SHOULD NOT",) s
-5 294 M
-( and "MAY" that appear in this document are to be interpreted as) s
-5 283 M
-( described in [RFC2119]) s
-5 261 M
-( The used data types and terminology are specified in the architecture) s
-5 250 M
-( document [SSH-ARCH]) s
-5 228 M
-( The architecture document also discusses the algorithm naming) s
-5 217 M
-( conventions that MUST be used with the SSH protocols.) s
-5 195 M
-(3.1 The Authentication Protocol Framework) s
-5 173 M
-( The server drives the authentication by telling the client which) s
-5 129 M
-(Ylonen & Moffat Expires March 2, 2003 [Page 3]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 4 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Authentication Protocol September 2002) s
-5 690 M
-( authentication methods can be used to continue the exchange at any) s
-5 679 M
-( given time. The client has the freedom to try the methods listed by) s
-5 668 M
-( the server in any order. This gives the server complete control over) s
-5 657 M
-( the authentication process if desired, but also gives enough) s
-5 646 M
-( flexibility for the client to use the methods it supports or that are) s
-5 635 M
-( most convenient for the user, when multiple methods are offered by) s
-5 624 M
-( the server.) s
-5 602 M
-( Authentication methods are identified by their name, as defined in) s
-5 591 M
-( [SSH-ARCH]. The "none" method is reserved, and MUST NOT be listed as) s
-5 580 M
-( supported. However, it MAY be sent by the client. The server MUST) s
-5 569 M
-( always reject this request, unless the client is to be allowed in) s
-5 558 M
-( without any authentication, in which case the server MUST accept this) s
-5 547 M
-( request. The main purpose of sending this request is to get the list) s
-5 536 M
-( of supported methods from the server.) s
-5 514 M
-( The server SHOULD have a timeout for authentication, and disconnect) s
-5 503 M
-( if the authentication has not been accepted within the timeout) s
-5 492 M
-( period. The RECOMMENDED timeout period is 10 minutes. Additionally,) s
-5 481 M
-( the implementation SHOULD limit the number of failed authentication) s
-5 470 M
-( attempts a client may perform in a single session \(the RECOMMENDED) s
-5 459 M
-( limit is 20 attempts\). If the threshold is exceeded, the server) s
-5 448 M
-( SHOULD disconnect.) s
-5 426 M
-(3.1.1 Authentication Requests) s
-5 404 M
-( All authentication requests MUST use the following message format.) s
-5 393 M
-( Only the first few fields are defined; the remaining fields depend on) s
-5 382 M
-( the authentication method.) s
-5 360 M
-( byte SSH_MSG_USERAUTH_REQUEST) s
-5 349 M
-( string user name \(in ISO-10646 UTF-8 encoding [RFC2279]\)) s
-5 338 M
-( string service name \(in US-ASCII\)) s
-5 327 M
-( string method name \(US-ASCII\)) s
-5 316 M
-( The rest of the packet is method-specific.) s
-5 294 M
-( The user name and service are repeated in every new authentication) s
-5 283 M
-( attempt, and MAY change. The server implementation MUST carefully) s
-5 272 M
-( check them in every message, and MUST flush any accumulated) s
-5 261 M
-( authentication states if they change. If it is unable to flush some) s
-5 250 M
-( authentication state, it MUST disconnect if the user or service name) s
-5 239 M
-( changes.) s
-5 217 M
-( The service name specifies the service to start after authentication.) s
-5 206 M
-( There may be several different authenticated services provided. If) s
-5 195 M
-( the requested service is not available, the server MAY disconnect) s
-5 184 M
-( immediately or at any later time. Sending a proper disconnect) s
-5 173 M
-( message is RECOMMENDED. In any case, if the service does not exist,) s
-5 129 M
-(Ylonen & Moffat Expires March 2, 2003 [Page 4]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (4,5) 3
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 5 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Authentication Protocol September 2002) s
-5 690 M
-( authentication MUST NOT be accepted.) s
-5 668 M
-( If the requested user does not exist, the server MAY disconnect, or) s
-5 657 M
-( MAY send a bogus list of acceptable authentication methods, but never) s
-5 646 M
-( accept any. This makes it possible for the server to avoid) s
-5 635 M
-( disclosing information on which accounts exist. In any case, if the) s
-5 624 M
-( user does not exist, the authentication request MUST NOT be accepted.) s
-5 602 M
-( While there is usually little point for clients to send requests that) s
-5 591 M
-( the server does not list as acceptable, sending such requests is not) s
-5 580 M
-( an error, and the server SHOULD simply reject requests that it does) s
-5 569 M
-( not recognize.) s
-5 547 M
-( An authentication request MAY result in a further exchange of) s
-5 536 M
-( messages. All such messages depend on the authentication method) s
-5 525 M
-( used, and the client MAY at any time continue with a new) s
-5 514 M
-( SSH_MSG_USERAUTH_REQUEST message, in which case the server MUST) s
-5 503 M
-( abandon the previous authentication attempt and continue with the new) s
-5 492 M
-( one.) s
-5 470 M
-(3.1.2 Responses to Authentication Requests) s
-5 448 M
-( If the server rejects the authentication request, it MUST respond) s
-5 437 M
-( with the following:) s
-5 415 M
-( byte SSH_MSG_USERAUTH_FAILURE) s
-5 404 M
-( string authentications that can continue) s
-5 393 M
-( boolean partial success) s
-5 371 M
-( "Authentications that can continue" is a comma-separated list of) s
-5 360 M
-( authentication method names that may productively continue the) s
-5 349 M
-( authentication dialog.) s
-5 327 M
-( It is RECOMMENDED that servers only include those methods in the list) s
-5 316 M
-( that are actually useful. However, it is not illegal to include) s
-5 305 M
-( methods that cannot be used to authenticate the user.) s
-5 283 M
-( Already successfully completed authentications SHOULD NOT be included) s
-5 272 M
-( in the list, unless they really should be performed again for some) s
-5 261 M
-( reason.) s
-5 239 M
-( "Partial success" MUST be TRUE if the authentication request to which) s
-5 228 M
-( this is a response was successful. It MUST be FALSE if the request) s
-5 217 M
-( was not successfully processed.) s
-5 195 M
-( When the server accepts authentication, it MUST respond with the) s
-5 184 M
-( following:) s
-5 129 M
-(Ylonen & Moffat Expires March 2, 2003 [Page 5]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 6 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Authentication Protocol September 2002) s
-5 690 M
-( byte SSH_MSG_USERAUTH_SUCCESS) s
-5 668 M
-( Note that this is not sent after each step in a multi-method) s
-5 657 M
-( authentication sequence, but only when the authentication is) s
-5 646 M
-( complete.) s
-5 624 M
-( The client MAY send several authentication requests without waiting) s
-5 613 M
-( for responses from previous requests. The server MUST process each) s
-5 602 M
-( request completely and acknowledge any failed requests with a) s
-5 591 M
-( SSH_MSG_USERAUTH_FAILURE message before processing the next request.) s
-5 569 M
-( A request that results in further exchange of messages will be) s
-5 558 M
-( aborted by a second request. It is not possible to send a second) s
-5 547 M
-( request without waiting for a response from the server, if the first) s
-5 536 M
-( request will result in further exchange of messages. No) s
-5 525 M
-( SSH_MSG_USERAUTH_FAILURE message will be sent for the aborted method.) s
-5 503 M
-( SSH_MSG_USERAUTH_SUCCESS MUST be sent only once. When) s
-5 492 M
-( SSH_MSG_USERAUTH_SUCCESS has been sent, any further authentication) s
-5 481 M
-( requests received after that SHOULD be silently ignored.) s
-5 459 M
-( Any non-authentication messages sent by the client after the request) s
-5 448 M
-( that resulted in SSH_MSG_USERAUTH_SUCCESS being sent MUST be passed) s
-5 437 M
-( to the service being run on top of this protocol. Such messages can) s
-5 426 M
-( be identified by their message numbers \(see Section Message Numbers) s
-5 415 M
-( \(Section 3.2\)\).) s
-5 393 M
-(3.1.3 The "none" Authentication Request) s
-5 371 M
-( A client may request a list of authentication methods that may) s
-5 360 M
-( continue by using the "none" authentication method.) s
-5 338 M
-( If no authentication at all is needed for the user, the server MUST) s
-5 327 M
-( return SSH_MSG_USERAUTH_SUCCESS. Otherwise, the server MUST return) s
-5 316 M
-( SSH_MSG_USERAUTH_FAILURE and MAY return with it a list of) s
-5 305 M
-( authentication methods that can continue.) s
-5 283 M
-( This method MUST NOT be listed as supported by the server.) s
-5 261 M
-(3.1.4 Completion of User Authentication) s
-5 239 M
-( Authentication is complete when the server has responded with) s
-5 228 M
-( SSH_MSG_USERAUTH_SUCCESS; all authentication related messages) s
-5 217 M
-( received after sending this message SHOULD be silently ignored.) s
-5 195 M
-( After sending SSH_MSG_USERAUTH_SUCCESS, the server starts the) s
-5 184 M
-( requested service.) s
-5 129 M
-(Ylonen & Moffat Expires March 2, 2003 [Page 6]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (6,7) 4
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 7 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Authentication Protocol September 2002) s
-5 690 M
-(3.1.5 Banner Message) s
-5 668 M
-( In some jurisdictions, sending a warning message before) s
-5 657 M
-( authentication may be relevant for getting legal protection. Many) s
-5 646 M
-( UNIX machines, for example, normally display text from `/etc/issue',) s
-5 635 M
-( or use "tcp wrappers" or similar software to display a banner before) s
-5 624 M
-( issuing a login prompt.) s
-5 602 M
-( The SSH server may send a SSH_MSG_USERAUTH_BANNER message at any time) s
-5 591 M
-( before authentication is successful. This message contains text to) s
-5 580 M
-( be displayed to the client user before authentication is attempted.) s
-5 569 M
-( The format is as follows:) s
-5 547 M
-( byte SSH_MSG_USERAUTH_BANNER) s
-5 536 M
-( string message \(ISO-10646 UTF-8\)) s
-5 525 M
-( string language tag \(as defined in [RFC3066]\)) s
-5 503 M
-( The client SHOULD by default display the message on the screen.) s
-5 492 M
-( However, since the message is likely to be sent for every login) s
-5 481 M
-( attempt, and since some client software will need to open a separate) s
-5 470 M
-( window for this warning, the client software may allow the user to) s
-5 459 M
-( explicitly disable the display of banners from the server. The) s
-5 448 M
-( message may consist of multiple lines.) s
-5 426 M
-( If the message string is displayed, control character filtering) s
-5 415 M
-( discussed in [SSH-ARCH] SHOULD be used to avoid attacks by sending) s
-5 404 M
-( terminal control characters.) s
-5 382 M
-(3.2 Authentication Protocol Message Numbers) s
-5 360 M
-( All message numbers used by this authentication protocol are in the) s
-5 349 M
-( range from 50 to 79, which is part of the range reserved for) s
-5 338 M
-( protocols running on top of the SSH transport layer protocol.) s
-5 316 M
-( Message numbers of 80 and higher are reserved for protocols running) s
-5 305 M
-( after this authentication protocol, so receiving one of them before) s
-5 294 M
-( authentication is complete is an error, to which the server MUST) s
-5 283 M
-( respond by disconnecting \(preferably with a proper disconnect message) s
-5 272 M
-( sent first to ease troubleshooting\).) s
-5 250 M
-( After successful authentication, such messages are passed to the) s
-5 239 M
-( higher-level service.) s
-5 217 M
-( These are the general authentication message codes:) s
-5 195 M
-( #define SSH_MSG_USERAUTH_REQUEST 50) s
-5 184 M
-( #define SSH_MSG_USERAUTH_FAILURE 51) s
-5 173 M
-( #define SSH_MSG_USERAUTH_SUCCESS 52) s
-5 129 M
-(Ylonen & Moffat Expires March 2, 2003 [Page 7]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 8 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Authentication Protocol September 2002) s
-5 690 M
-( #define SSH_MSG_USERAUTH_BANNER 53) s
-5 668 M
-( In addition to the above, there is a range of message numbers) s
-5 657 M
-( \(60..79\) reserved for method-specific messages. These messages are) s
-5 646 M
-( only sent by the server \(client sends only SSH_MSG_USERAUTH_REQUEST) s
-5 635 M
-( messages\). Different authentication methods reuse the same message) s
-5 624 M
-( numbers.) s
-5 602 M
-(3.3 Public Key Authentication Method: publickey) s
-5 580 M
-( The only REQUIRED authentication method is public key authentication.) s
-5 569 M
-( All implementations MUST support this method; however, not all users) s
-5 558 M
-( need to have public keys, and most local policies are not likely to) s
-5 547 M
-( require public key authentication for all users in the near future.) s
-5 525 M
-( With this method, the possession of a private key serves as) s
-5 514 M
-( authentication. This method works by sending a signature created) s
-5 503 M
-( with a private key of the user. The server MUST check that the key) s
-5 492 M
-( is a valid authenticator for the user, and MUST check that the) s
-5 481 M
-( signature is valid. If both hold, the authentication request MUST be) s
-5 470 M
-( accepted; otherwise it MUST be rejected. \(Note that the server MAY) s
-5 459 M
-( require additional authentications after successful authentication.\)) s
-5 437 M
-( Private keys are often stored in an encrypted form at the client) s
-5 426 M
-( host, and the user must supply a passphrase before the signature can) s
-5 415 M
-( be generated. Even if they are not, the signing operation involves) s
-5 404 M
-( some expensive computation. To avoid unnecessary processing and user) s
-5 393 M
-( interaction, the following message is provided for querying whether) s
-5 382 M
-( authentication using the key would be acceptable.) s
-5 360 M
-( byte SSH_MSG_USERAUTH_REQUEST) s
-5 349 M
-( string user name) s
-5 338 M
-( string service) s
-5 327 M
-( string "publickey") s
-5 316 M
-( boolean FALSE) s
-5 305 M
-( string public key algorithm name) s
-5 294 M
-( string public key blob) s
-5 272 M
-( Public key algorithms are defined in the transport layer) s
-5 261 M
-( specification [SSH-TRANS]. The public key blob may contain) s
-5 250 M
-( certificates.) s
-5 228 M
-( Any public key algorithm may be offered for use in authentication.) s
-5 217 M
-( In particular, the list is not constrained by what was negotiated) s
-5 206 M
-( during key exchange. If the server does not support some algorithm,) s
-5 195 M
-( it MUST simply reject the request.) s
-5 173 M
-( The server MUST respond to this message with either) s
-5 129 M
-(Ylonen & Moffat Expires March 2, 2003 [Page 8]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (8,9) 5
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 9 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Authentication Protocol September 2002) s
-5 690 M
-( SSH_MSG_USERAUTH_FAILURE or with the following:) s
-5 668 M
-( byte SSH_MSG_USERAUTH_PK_OK) s
-5 657 M
-( string public key algorithm name from the request) s
-5 646 M
-( string public key blob from the request) s
-5 624 M
-( To perform actual authentication, the client MAY then send a) s
-5 613 M
-( signature generated using the private key. The client MAY send the) s
-5 602 M
-( signature directly without first verifying whether the key is) s
-5 591 M
-( acceptable. The signature is sent using the following packet:) s
-5 569 M
-( byte SSH_MSG_USERAUTH_REQUEST) s
-5 558 M
-( string user name) s
-5 547 M
-( string service) s
-5 536 M
-( string "publickey") s
-5 525 M
-( boolean TRUE) s
-5 514 M
-( string public key algorithm name) s
-5 503 M
-( string public key to be used for authentication) s
-5 492 M
-( string signature) s
-5 470 M
-( Signature is a signature by the corresponding private key over the) s
-5 459 M
-( following data, in the following order:) s
-5 437 M
-( string session identifier) s
-5 426 M
-( byte SSH_MSG_USERAUTH_REQUEST) s
-5 415 M
-( string user name) s
-5 404 M
-( string service) s
-5 393 M
-( string "publickey") s
-5 382 M
-( boolean TRUE) s
-5 371 M
-( string public key algorithm name) s
-5 360 M
-( string public key to be used for authentication) s
-5 338 M
-( When the server receives this message, it MUST check whether the) s
-5 327 M
-( supplied key is acceptable for authentication, and if so, it MUST) s
-5 316 M
-( check whether the signature is correct.) s
-5 294 M
-( If both checks succeed, this method is successful. Note that the) s
-5 283 M
-( server may require additional authentications. The server MUST) s
-5 272 M
-( respond with SSH_MSG_USERAUTH_SUCCESS \(if no more authentications are) s
-5 261 M
-( needed\), or SSH_MSG_USERAUTH_FAILURE \(if the request failed, or more) s
-5 250 M
-( authentications are needed\).) s
-5 228 M
-( The following method-specific message numbers are used by the) s
-5 217 M
-( publickey authentication method.) s
-5 195 M
-( /* Key-based */) s
-5 184 M
-( #define SSH_MSG_USERAUTH_PK_OK 60) s
-5 129 M
-(Ylonen & Moffat Expires March 2, 2003 [Page 9]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 10 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Authentication Protocol September 2002) s
-5 690 M
-(3.4 Password Authentication Method: password) s
-5 668 M
-( Password authentication uses the following packets. Note that a) s
-5 657 M
-( server MAY request the user to change the password. All) s
-5 646 M
-( implementations SHOULD support password authentication.) s
-5 624 M
-( byte SSH_MSG_USERAUTH_REQUEST) s
-5 613 M
-( string user name) s
-5 602 M
-( string service) s
-5 591 M
-( string "password") s
-5 580 M
-( boolean FALSE) s
-5 569 M
-( string plaintext password \(ISO-10646 UTF-8\)) s
-5 547 M
-( Note that the password is encoded in ISO-10646 UTF-8. It is up to) s
-5 536 M
-( the server how it interprets the password and validates it against) s
-5 525 M
-( the password database. However, if the client reads the password in) s
-5 514 M
-( some other encoding \(e.g., ISO 8859-1 \(ISO Latin1\)\), it MUST convert) s
-5 503 M
-( the password to ISO-10646 UTF-8 before transmitting, and the server) s
-5 492 M
-( MUST convert the password to the encoding used on that system for) s
-5 481 M
-( passwords.) s
-5 459 M
-( Note that even though the cleartext password is transmitted in the) s
-5 448 M
-( packet, the entire packet is encrypted by the transport layer. Both) s
-5 437 M
-( the server and the client should check whether the underlying) s
-5 426 M
-( transport layer provides confidentiality \(i.e., if encryption is) s
-5 415 M
-( being used\). If no confidentiality is provided \(none cipher\),) s
-5 404 M
-( password authentication SHOULD be disabled. If there is no) s
-5 393 M
-( confidentiality or no MAC, password change SHOULD be disabled.) s
-5 371 M
-( Normally, the server responds to this message with success or) s
-5 360 M
-( failure. However, if the password has expired the server SHOULD) s
-5 349 M
-( indicate this by responding with SSH_MSG_USERAUTH_PASSWD_CHANGEREQ.) s
-5 338 M
-( In anycase the server MUST NOT allow an expired password to be used) s
-5 327 M
-( for authentication.) s
-5 305 M
-( byte SSH_MSG_USERAUTH_PASSWD_CHANGEREQ) s
-5 294 M
-( string prompt \(ISO-10646 UTF-8\)) s
-5 283 M
-( string language tag \(as defined in [RFC3066]\)) s
-5 261 M
-( In this case, the client MAY continue with a different authentication) s
-5 250 M
-( method, or request a new password from the user and retry password) s
-5 239 M
-( authentication using the following message. The client MAY also send) s
-5 228 M
-( this message instead of the normal password authentication request) s
-5 217 M
-( without the server asking for it.) s
-5 195 M
-( byte SSH_MSG_USERAUTH_REQUEST) s
-5 184 M
-( string user name) s
-5 173 M
-( string service) s
-5 129 M
-(Ylonen & Moffat Expires March 2, 2003 [Page 10]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (10,11) 6
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 11 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Authentication Protocol September 2002) s
-5 690 M
-( string "password") s
-5 679 M
-( boolean TRUE) s
-5 668 M
-( string plaintext old password \(ISO-10646 UTF-8\)) s
-5 657 M
-( string plaintext new password \(ISO-10646 UTF-8\)) s
-5 635 M
-( The server must reply to request message with) s
-5 624 M
-( SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE, or another) s
-5 613 M
-( SSH_MSG_USERAUTH_PASSWD_CHANGEREQ. The meaning of these is as) s
-5 602 M
-( follows:) s
-5 580 M
-( SSH_MSG_USERAUTH_SUCCESS The password has been changed, and) s
-5 569 M
-( authentication has been successfully completed.) s
-5 547 M
-( SSH_MSG_USERAUTH_FAILURE with partial success The password has) s
-5 536 M
-( been changed, but more authentications are needed.) s
-5 514 M
-( SSH_MSG_USERAUTH_FAILURE without partial success The password has) s
-5 503 M
-( not been changed. Either password changing was not supported, or) s
-5 492 M
-( the old password was bad. Note that if the server has already) s
-5 481 M
-( sent SSH_MSG_USERAUTH_PASSWD_CHANGEREQ, we know that it supports) s
-5 470 M
-( changing the password.) s
-5 448 M
-( SSH_MSG_USERAUTH_CHANGEREQ The password was not changed because) s
-5 437 M
-( the new password was not acceptable \(e.g. too easy to guess\).) s
-5 415 M
-( The following method-specific message numbers are used by the) s
-5 404 M
-( password authentication method.) s
-5 382 M
-( #define SSH_MSG_USERAUTH_PASSWD_CHANGEREQ 60) s
-5 349 M
-(3.5 Host-Based Authentication: hostbased) s
-5 327 M
-( Some sites wish to allow authentication based on the host where the) s
-5 316 M
-( user is coming from, and the user name on the remote host. While) s
-5 305 M
-( this form of authentication is not suitable for high-security sites,) s
-5 294 M
-( it can be very convenient in many environments. This form of) s
-5 283 M
-( authentication is OPTIONAL. When used, special care SHOULD be taken) s
-5 272 M
-( to prevent a regular user from obtaining the private host key.) s
-5 250 M
-( The client requests this form of authentication by sending the) s
-5 239 M
-( following message. It is similar to the UNIX "rhosts" and) s
-5 228 M
-( "hosts.equiv" styles of authentication, except that the identity of) s
-5 217 M
-( the client host is checked more rigorously.) s
-5 195 M
-( This method works by having the client send a signature created with) s
-5 184 M
-( the private key of the client host, which the server checks with that) s
-5 173 M
-( host's public key. Once the client host's identity is established,) s
-5 129 M
-(Ylonen & Moffat Expires March 2, 2003 [Page 11]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 12 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Authentication Protocol September 2002) s
-5 690 M
-( authorization \(but no further authentication\) is performed based on) s
-5 679 M
-( the user names on the server and the client, and the client host) s
-5 668 M
-( name.) s
-5 646 M
-( byte SSH_MSG_USERAUTH_REQUEST) s
-5 635 M
-( string user name) s
-5 624 M
-( string service) s
-5 613 M
-( string "hostbased") s
-5 602 M
-( string public key algorithm for host key) s
-5 591 M
-( string public host key and certificates for client host) s
-5 580 M
-( string client host name \(FQDN; US-ASCII\)) s
-5 569 M
-( string user name on the client host \(ISO-10646 UTF-8\)) s
-5 558 M
-( string signature) s
-5 536 M
-( Public key algorithm names for use in "public key algorithm for host) s
-5 525 M
-( key" are defined in the transport layer specification. The "public) s
-5 514 M
-( host key for client host" may include certificates.) s
-5 492 M
-( Signature is a signature with the private host key of the following) s
-5 481 M
-( data, in this order:) s
-5 459 M
-( string session identifier) s
-5 448 M
-( byte SSH_MSG_USERAUTH_REQUEST) s
-5 437 M
-( string user name) s
-5 426 M
-( string service) s
-5 415 M
-( string "hostbased") s
-5 404 M
-( string public key algorithm for host key) s
-5 393 M
-( string public host key and certificates for client host) s
-5 382 M
-( string client host name \(FQDN; US-ASCII\)) s
-5 371 M
-( string user name on the client host\(ISO-10646 UTF-8\)) s
-5 349 M
-( The server MUST verify that the host key actually belongs to the) s
-5 338 M
-( client host named in the message, that the given user on that host is) s
-5 327 M
-( allowed to log in, and that the signature is a valid signature on the) s
-5 316 M
-( appropriate value by the given host key. The server MAY ignore the) s
-5 305 M
-( client user name, if it wants to authenticate only the client host.) s
-5 283 M
-( It is RECOMMENDED that whenever possible, the server perform) s
-5 272 M
-( additional checks to verify that the network address obtained from) s
-5 261 M
-( the \(untrusted\) network matches the given client host name. This) s
-5 250 M
-( makes exploiting compromised host keys more difficult. Note that) s
-5 239 M
-( this may require special handling for connections coming through a) s
-5 228 M
-( firewall.) s
-5 206 M
-(4. Security Considerations) s
-5 184 M
-( The purpose of this protocol is to perform client user) s
-5 173 M
-( authentication. It assumed that this runs over a secure transport) s
-5 129 M
-(Ylonen & Moffat Expires March 2, 2003 [Page 12]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (12,13) 7
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 13 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Authentication Protocol September 2002) s
-5 690 M
-( layer protocol, which has already authenticated the server machine,) s
-5 679 M
-( established an encrypted communications channel, and computed a) s
-5 668 M
-( unique session identifier for this session. The transport layer) s
-5 657 M
-( provides forward secrecy for password authentication and other) s
-5 646 M
-( methods that rely on secret data.) s
-5 624 M
-( Full security considerations for this protocol are provided in) s
-5 613 M
-( Section 8 of [SSH-ARCH]) s
-5 591 M
-(Normative) s
-5 569 M
-( [SSH-ARCH]) s
-5 558 M
-( Ylonen, T., "SSH Protocol Architecture", I-D) s
-5 547 M
-( draft-ietf-architecture-15.txt, Oct 2003.) s
-5 525 M
-( [SSH-TRANS]) s
-5 514 M
-( Ylonen, T., "SSH Transport Layer Protocol", I-D) s
-5 503 M
-( draft-ietf-transport-17.txt, Oct 2003.) s
-5 481 M
-( [SSH-USERAUTH]) s
-5 470 M
-( Ylonen, T., "SSH Authentication Protocol", I-D) s
-5 459 M
-( draft-ietf-userauth-18.txt, Oct 2003.) s
-5 437 M
-( [SSH-CONNECT]) s
-5 426 M
-( Ylonen, T., "SSH Connection Protocol", I-D) s
-5 415 M
-( draft-ietf-connect-18.txt, Oct 2003.) s
-5 393 M
-( [SSH-NUMBERS]) s
-5 382 M
-( Lehtinen, S. and D. Moffat, "SSH Protocol Assigned) s
-5 371 M
-( Numbers", I-D draft-ietf-secsh-assignednumbers-05.txt, Oct) s
-5 360 M
-( 2003.) s
-5 338 M
-( [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate) s
-5 327 M
-( Requirement Levels", BCP 14, RFC 2119, March 1997.) s
-5 305 M
-(Informative) s
-5 283 M
-( [RFC3066] Alvestrand, H., "Tags for the Identification of) s
-5 272 M
-( Languages", BCP 47, RFC 3066, January 2001.) s
-5 250 M
-( [RFC2279] Yergeau, F., "UTF-8, a transformation format of ISO) s
-5 239 M
-( 10646", RFC 2279, January 1998.) s
-5 129 M
-(Ylonen & Moffat Expires March 2, 2003 [Page 13]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 14 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Authentication Protocol September 2002) s
-5 690 M
-(Authors' Addresses) s
-5 668 M
-( Tatu Ylonen) s
-5 657 M
-( SSH Communications Security Corp) s
-5 646 M
-( Fredrikinkatu 42) s
-5 635 M
-( HELSINKI FIN-00100) s
-5 624 M
-( Finland) s
-5 602 M
-( EMail: [email protected]) s
-5 569 M
-( Darren J. Moffat \(editor\)) s
-5 558 M
-( Sun Microsystems, Inc) s
-5 547 M
-( 17 Network Circle) s
-5 536 M
-( Menlo Park 95025) s
-5 525 M
-( USA) s
-5 503 M
-( EMail: [email protected]) s
-5 129 M
-(Ylonen & Moffat Expires March 2, 2003 [Page 14]) s
-_R
-S
-PStoPSsaved restore
-%%Page: (14,15) 8
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 0.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-/showpage{}def/copypage{}def/erasepage{}def
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 15 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Authentication Protocol September 2002) s
-5 690 M
-(Intellectual Property Statement) s
-5 668 M
-( The IETF takes no position regarding the validity or scope of any) s
-5 657 M
-( intellectual property or other rights that might be claimed to) s
-5 646 M
-( pertain to the implementation or use of the technology described in) s
-5 635 M
-( this document or the extent to which any license under such rights) s
-5 624 M
-( might or might not be available; neither does it represent that it) s
-5 613 M
-( has made any effort to identify any such rights. Information on the) s
-5 602 M
-( IETF's procedures with respect to rights in standards-track and) s
-5 591 M
-( standards-related documentation can be found in BCP-11. Copies of) s
-5 580 M
-( claims of rights made available for publication and any assurances of) s
-5 569 M
-( licenses to be made available, or the result of an attempt made to) s
-5 558 M
-( obtain a general license or permission for the use of such) s
-5 547 M
-( proprietary rights by implementors or users of this specification can) s
-5 536 M
-( be obtained from the IETF Secretariat.) s
-5 514 M
-( The IETF invites any interested party to bring to its attention any) s
-5 503 M
-( copyrights, patents or patent applications, or other proprietary) s
-5 492 M
-( rights which may cover technology that may be required to practice) s
-5 481 M
-( this standard. Please address the information to the IETF Executive) s
-5 470 M
-( Director.) s
-5 448 M
-( The IETF has been notified of intellectual property rights claimed in) s
-5 437 M
-( regard to some or all of the specification contained in this) s
-5 426 M
-( document. For more information consult the online list of claimed) s
-5 415 M
-( rights.) s
-5 382 M
-(Full Copyright Statement) s
-5 360 M
-( Copyright \(C\) The Internet Society \(2002\). All Rights Reserved.) s
-5 338 M
-( This document and translations of it may be copied and furnished to) s
-5 327 M
-( others, and derivative works that comment on or otherwise explain it) s
-5 316 M
-( or assist in its implementation may be prepared, copied, published) s
-5 305 M
-( and distributed, in whole or in part, without restriction of any) s
-5 294 M
-( kind, provided that the above copyright notice and this paragraph are) s
-5 283 M
-( included on all such copies and derivative works. However, this) s
-5 272 M
-( document itself may not be modified in any way, such as by removing) s
-5 261 M
-( the copyright notice or references to the Internet Society or other) s
-5 250 M
-( Internet organizations, except as needed for the purpose of) s
-5 239 M
-( developing Internet standards in which case the procedures for) s
-5 228 M
-( copyrights defined in the Internet Standards process must be) s
-5 217 M
-( followed, or as required to translate it into languages other than) s
-5 206 M
-( English.) s
-5 184 M
-( The limited permissions granted above are perpetual and will not be) s
-5 173 M
-( revoked by the Internet Society or its successors or assignees.) s
-5 129 M
-(Ylonen & Moffat Expires March 2, 2003 [Page 15]) s
-_R
-S
-PStoPSsaved restore
-userdict/PStoPSsaved save put
-PStoPSmatrix setmatrix
-595.000000 421.271378 translate
-90 rotate
-0.706651 dup scale
-userdict/PStoPSmatrix matrix currentmatrix put
-userdict/PStoPSclip{0 0 moveto
- 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
- closepath}put initclip
-PStoPSxform concat
-%%BeginPageSetup
-_S
-75 0 translate
-/pagenum 16 def
-/fname () def
-/fdir () def
-/ftail () def
-/user_header_p false def
-%%EndPageSetup
-5 723 M
-(Internet-Draft SSH Authentication Protocol September 2002) s
-5 690 M
-( This document and the information contained herein is provided on an) s
-5 679 M
-( "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING) s
-5 668 M
-( TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING) s
-5 657 M
-( BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION) s
-5 646 M
-( HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF) s
-5 635 M
-( MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.) s
-5 602 M
-(Acknowledgment) s
-5 580 M
-( Funding for the RFC Editor function is currently provided by the) s
-5 569 M
-( Internet Society.) s
-5 129 M
-(Ylonen & Moffat Expires March 2, 2003 [Page 16]) s
-_R
-S
-PStoPSsaved restore
-%%Trailer
-%%Pages: 16
-%%DocumentNeededResources: font Courier-Bold Courier
-%%EOF
diff --git a/lib/ssh/doc/standard/draft-ietf-secsh-userauth-18.txt b/lib/ssh/doc/standard/draft-ietf-secsh-userauth-18.txt
deleted file mode 100644
index 9dae578a35..0000000000
--- a/lib/ssh/doc/standard/draft-ietf-secsh-userauth-18.txt
+++ /dev/null
@@ -1,896 +0,0 @@
-
-
-
-Network Working Group T. Ylonen
-Internet-Draft SSH Communications Security Corp
-Expires: March 2, 2003 D. Moffat, Ed.
- Sun Microsystems, Inc
- September 2002
-
-
- SSH Authentication Protocol
- draft-ietf-secsh-userauth-18.txt
-
-Status of this Memo
-
- This document is an Internet-Draft and is in full conformance with
- all provisions of Section 10 of RFC2026.
-
- Internet-Drafts are working documents of the Internet Engineering
- Task Force (IETF), its areas, and its working groups. Note that other
- groups may also distribute working documents as Internet-Drafts.
-
- Internet-Drafts are draft documents valid for a maximum of six months
- and may be updated, replaced, or obsoleted by other documents at any
- time. It is inappropriate to use Internet-Drafts as reference
- material or to cite them other than as "work in progress."
-
- The list of current Internet-Drafts can be accessed at http://
- www.ietf.org/ietf/1id-abstracts.txt.
-
- The list of Internet-Draft Shadow Directories can be accessed at
- http://www.ietf.org/shadow.html.
-
- This Internet-Draft will expire on March 2, 2003.
-
-Copyright Notice
-
- Copyright (C) The Internet Society (2002). All Rights Reserved.
-
-Abstract
-
- SSH is a protocol for secure remote login and other secure network
- services over an insecure network. This document describes the SSH
- authentication protocol framework and public key, password, and
- host-based client authentication methods. Additional authentication
- methods are described in separate documents. The SSH authentication
- protocol runs on top of the SSH transport layer protocol and provides
- a single authenticated tunnel for the SSH connection protocol.
-
-
-
-
-
-
-
-Ylonen & Moffat Expires March 2, 2003 [Page 1]
-
-Internet-Draft SSH Authentication Protocol September 2002
-
-
-Table of Contents
-
- 1. Contributors . . . . . . . . . . . . . . . . . . . . . . . . 3
- 2. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3
- 3. Conventions Used in This Document . . . . . . . . . . . . . 3
- 3.1 The Authentication Protocol Framework . . . . . . . . . . . 3
- 3.1.1 Authentication Requests . . . . . . . . . . . . . . . . . . 4
- 3.1.2 Responses to Authentication Requests . . . . . . . . . . . . 5
- 3.1.3 The "none" Authentication Request . . . . . . . . . . . . . 6
- 3.1.4 Completion of User Authentication . . . . . . . . . . . . . 6
- 3.1.5 Banner Message . . . . . . . . . . . . . . . . . . . . . . . 7
- 3.2 Authentication Protocol Message Numbers . . . . . . . . . . 7
- 3.3 Public Key Authentication Method: publickey . . . . . . . . 8
- 3.4 Password Authentication Method: password . . . . . . . . . . 10
- 3.5 Host-Based Authentication: hostbased . . . . . . . . . . . . 11
- 4. Security Considerations . . . . . . . . . . . . . . . . . . 12
- Normative . . . . . . . . . . . . . . . . . . . . . . . . . 13
- Informative . . . . . . . . . . . . . . . . . . . . . . . . 13
- Authors' Addresses . . . . . . . . . . . . . . . . . . . . . 14
- Intellectual Property and Copyright Statements . . . . . . . 15
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Ylonen & Moffat Expires March 2, 2003 [Page 2]
-
-Internet-Draft SSH Authentication Protocol September 2002
-
-
-1. Contributors
-
- The major original contributors of this document were: Tatu Ylonen,
- Tero Kivinen, Timo J. Rinne, Sami Lehtinen (all of SSH Communications
- Security Corp), and Markku-Juhani O. Saarinen (University of
- Jyvaskyla)
-
- The document editor is: [email protected]. Comments on this
- internet draft should be sent to the IETF SECSH working group,
- details at: http://ietf.org/html.charters/secsh-charter.html
-
-2. Introduction
-
- The SSH authentication protocol is a general-purpose user
- authentication protocol. It is intended to be run over the SSH
- transport layer protocol [SSH-TRANS]. This protocol assumes that the
- underlying protocols provide integrity and confidentiality
- protection.
-
- This document should be read only after reading the SSH architecture
- document [SSH-ARCH]. This document freely uses terminology and
- notation from the architecture document without reference or further
- explanation.
-
- The service name for this protocol is "ssh-userauth".
-
- When this protocol starts, it receives the session identifier from
- the lower-level protocol (this is the exchange hash H from the first
- key exchange). The session identifier uniquely identifies this
- session and is suitable for signing in order to prove ownership of a
- private key. This protocol also needs to know whether the lower-level
- protocol provides confidentiality protection.
-
-3. Conventions Used in This Document
-
- The keywords "MUST", "MUST NOT", "REQUIRED", "SHOULD", "SHOULD NOT",
- and "MAY" that appear in this document are to be interpreted as
- described in [RFC2119]
-
- The used data types and terminology are specified in the architecture
- document [SSH-ARCH]
-
- The architecture document also discusses the algorithm naming
- conventions that MUST be used with the SSH protocols.
-
-3.1 The Authentication Protocol Framework
-
- The server drives the authentication by telling the client which
-
-
-
-Ylonen & Moffat Expires March 2, 2003 [Page 3]
-
-Internet-Draft SSH Authentication Protocol September 2002
-
-
- authentication methods can be used to continue the exchange at any
- given time. The client has the freedom to try the methods listed by
- the server in any order. This gives the server complete control over
- the authentication process if desired, but also gives enough
- flexibility for the client to use the methods it supports or that are
- most convenient for the user, when multiple methods are offered by
- the server.
-
- Authentication methods are identified by their name, as defined in
- [SSH-ARCH]. The "none" method is reserved, and MUST NOT be listed as
- supported. However, it MAY be sent by the client. The server MUST
- always reject this request, unless the client is to be allowed in
- without any authentication, in which case the server MUST accept this
- request. The main purpose of sending this request is to get the list
- of supported methods from the server.
-
- The server SHOULD have a timeout for authentication, and disconnect
- if the authentication has not been accepted within the timeout
- period. The RECOMMENDED timeout period is 10 minutes. Additionally,
- the implementation SHOULD limit the number of failed authentication
- attempts a client may perform in a single session (the RECOMMENDED
- limit is 20 attempts). If the threshold is exceeded, the server
- SHOULD disconnect.
-
-3.1.1 Authentication Requests
-
- All authentication requests MUST use the following message format.
- Only the first few fields are defined; the remaining fields depend on
- the authentication method.
-
- byte SSH_MSG_USERAUTH_REQUEST
- string user name (in ISO-10646 UTF-8 encoding [RFC2279])
- string service name (in US-ASCII)
- string method name (US-ASCII)
- The rest of the packet is method-specific.
-
- The user name and service are repeated in every new authentication
- attempt, and MAY change. The server implementation MUST carefully
- check them in every message, and MUST flush any accumulated
- authentication states if they change. If it is unable to flush some
- authentication state, it MUST disconnect if the user or service name
- changes.
-
- The service name specifies the service to start after authentication.
- There may be several different authenticated services provided. If
- the requested service is not available, the server MAY disconnect
- immediately or at any later time. Sending a proper disconnect
- message is RECOMMENDED. In any case, if the service does not exist,
-
-
-
-Ylonen & Moffat Expires March 2, 2003 [Page 4]
-
-Internet-Draft SSH Authentication Protocol September 2002
-
-
- authentication MUST NOT be accepted.
-
- If the requested user does not exist, the server MAY disconnect, or
- MAY send a bogus list of acceptable authentication methods, but never
- accept any. This makes it possible for the server to avoid
- disclosing information on which accounts exist. In any case, if the
- user does not exist, the authentication request MUST NOT be accepted.
-
- While there is usually little point for clients to send requests that
- the server does not list as acceptable, sending such requests is not
- an error, and the server SHOULD simply reject requests that it does
- not recognize.
-
- An authentication request MAY result in a further exchange of
- messages. All such messages depend on the authentication method
- used, and the client MAY at any time continue with a new
- SSH_MSG_USERAUTH_REQUEST message, in which case the server MUST
- abandon the previous authentication attempt and continue with the new
- one.
-
-3.1.2 Responses to Authentication Requests
-
- If the server rejects the authentication request, it MUST respond
- with the following:
-
- byte SSH_MSG_USERAUTH_FAILURE
- string authentications that can continue
- boolean partial success
-
- "Authentications that can continue" is a comma-separated list of
- authentication method names that may productively continue the
- authentication dialog.
-
- It is RECOMMENDED that servers only include those methods in the list
- that are actually useful. However, it is not illegal to include
- methods that cannot be used to authenticate the user.
-
- Already successfully completed authentications SHOULD NOT be included
- in the list, unless they really should be performed again for some
- reason.
-
- "Partial success" MUST be TRUE if the authentication request to which
- this is a response was successful. It MUST be FALSE if the request
- was not successfully processed.
-
- When the server accepts authentication, it MUST respond with the
- following:
-
-
-
-
-Ylonen & Moffat Expires March 2, 2003 [Page 5]
-
-Internet-Draft SSH Authentication Protocol September 2002
-
-
- byte SSH_MSG_USERAUTH_SUCCESS
-
- Note that this is not sent after each step in a multi-method
- authentication sequence, but only when the authentication is
- complete.
-
- The client MAY send several authentication requests without waiting
- for responses from previous requests. The server MUST process each
- request completely and acknowledge any failed requests with a
- SSH_MSG_USERAUTH_FAILURE message before processing the next request.
-
- A request that results in further exchange of messages will be
- aborted by a second request. It is not possible to send a second
- request without waiting for a response from the server, if the first
- request will result in further exchange of messages. No
- SSH_MSG_USERAUTH_FAILURE message will be sent for the aborted method.
-
- SSH_MSG_USERAUTH_SUCCESS MUST be sent only once. When
- SSH_MSG_USERAUTH_SUCCESS has been sent, any further authentication
- requests received after that SHOULD be silently ignored.
-
- Any non-authentication messages sent by the client after the request
- that resulted in SSH_MSG_USERAUTH_SUCCESS being sent MUST be passed
- to the service being run on top of this protocol. Such messages can
- be identified by their message numbers (see Section Message Numbers
- (Section 3.2)).
-
-3.1.3 The "none" Authentication Request
-
- A client may request a list of authentication methods that may
- continue by using the "none" authentication method.
-
- If no authentication at all is needed for the user, the server MUST
- return SSH_MSG_USERAUTH_SUCCESS. Otherwise, the server MUST return
- SSH_MSG_USERAUTH_FAILURE and MAY return with it a list of
- authentication methods that can continue.
-
- This method MUST NOT be listed as supported by the server.
-
-3.1.4 Completion of User Authentication
-
- Authentication is complete when the server has responded with
- SSH_MSG_USERAUTH_SUCCESS; all authentication related messages
- received after sending this message SHOULD be silently ignored.
-
- After sending SSH_MSG_USERAUTH_SUCCESS, the server starts the
- requested service.
-
-
-
-
-Ylonen & Moffat Expires March 2, 2003 [Page 6]
-
-Internet-Draft SSH Authentication Protocol September 2002
-
-
-3.1.5 Banner Message
-
- In some jurisdictions, sending a warning message before
- authentication may be relevant for getting legal protection. Many
- UNIX machines, for example, normally display text from `/etc/issue',
- or use "tcp wrappers" or similar software to display a banner before
- issuing a login prompt.
-
- The SSH server may send a SSH_MSG_USERAUTH_BANNER message at any time
- before authentication is successful. This message contains text to
- be displayed to the client user before authentication is attempted.
- The format is as follows:
-
- byte SSH_MSG_USERAUTH_BANNER
- string message (ISO-10646 UTF-8)
- string language tag (as defined in [RFC3066])
-
- The client SHOULD by default display the message on the screen.
- However, since the message is likely to be sent for every login
- attempt, and since some client software will need to open a separate
- window for this warning, the client software may allow the user to
- explicitly disable the display of banners from the server. The
- message may consist of multiple lines.
-
- If the message string is displayed, control character filtering
- discussed in [SSH-ARCH] SHOULD be used to avoid attacks by sending
- terminal control characters.
-
-3.2 Authentication Protocol Message Numbers
-
- All message numbers used by this authentication protocol are in the
- range from 50 to 79, which is part of the range reserved for
- protocols running on top of the SSH transport layer protocol.
-
- Message numbers of 80 and higher are reserved for protocols running
- after this authentication protocol, so receiving one of them before
- authentication is complete is an error, to which the server MUST
- respond by disconnecting (preferably with a proper disconnect message
- sent first to ease troubleshooting).
-
- After successful authentication, such messages are passed to the
- higher-level service.
-
- These are the general authentication message codes:
-
- #define SSH_MSG_USERAUTH_REQUEST 50
- #define SSH_MSG_USERAUTH_FAILURE 51
- #define SSH_MSG_USERAUTH_SUCCESS 52
-
-
-
-Ylonen & Moffat Expires March 2, 2003 [Page 7]
-
-Internet-Draft SSH Authentication Protocol September 2002
-
-
- #define SSH_MSG_USERAUTH_BANNER 53
-
- In addition to the above, there is a range of message numbers
- (60..79) reserved for method-specific messages. These messages are
- only sent by the server (client sends only SSH_MSG_USERAUTH_REQUEST
- messages). Different authentication methods reuse the same message
- numbers.
-
-3.3 Public Key Authentication Method: publickey
-
- The only REQUIRED authentication method is public key authentication.
- All implementations MUST support this method; however, not all users
- need to have public keys, and most local policies are not likely to
- require public key authentication for all users in the near future.
-
- With this method, the possession of a private key serves as
- authentication. This method works by sending a signature created
- with a private key of the user. The server MUST check that the key
- is a valid authenticator for the user, and MUST check that the
- signature is valid. If both hold, the authentication request MUST be
- accepted; otherwise it MUST be rejected. (Note that the server MAY
- require additional authentications after successful authentication.)
-
- Private keys are often stored in an encrypted form at the client
- host, and the user must supply a passphrase before the signature can
- be generated. Even if they are not, the signing operation involves
- some expensive computation. To avoid unnecessary processing and user
- interaction, the following message is provided for querying whether
- authentication using the key would be acceptable.
-
- byte SSH_MSG_USERAUTH_REQUEST
- string user name
- string service
- string "publickey"
- boolean FALSE
- string public key algorithm name
- string public key blob
-
- Public key algorithms are defined in the transport layer
- specification [SSH-TRANS]. The public key blob may contain
- certificates.
-
- Any public key algorithm may be offered for use in authentication.
- In particular, the list is not constrained by what was negotiated
- during key exchange. If the server does not support some algorithm,
- it MUST simply reject the request.
-
- The server MUST respond to this message with either
-
-
-
-Ylonen & Moffat Expires March 2, 2003 [Page 8]
-
-Internet-Draft SSH Authentication Protocol September 2002
-
-
- SSH_MSG_USERAUTH_FAILURE or with the following:
-
- byte SSH_MSG_USERAUTH_PK_OK
- string public key algorithm name from the request
- string public key blob from the request
-
- To perform actual authentication, the client MAY then send a
- signature generated using the private key. The client MAY send the
- signature directly without first verifying whether the key is
- acceptable. The signature is sent using the following packet:
-
- byte SSH_MSG_USERAUTH_REQUEST
- string user name
- string service
- string "publickey"
- boolean TRUE
- string public key algorithm name
- string public key to be used for authentication
- string signature
-
- Signature is a signature by the corresponding private key over the
- following data, in the following order:
-
- string session identifier
- byte SSH_MSG_USERAUTH_REQUEST
- string user name
- string service
- string "publickey"
- boolean TRUE
- string public key algorithm name
- string public key to be used for authentication
-
- When the server receives this message, it MUST check whether the
- supplied key is acceptable for authentication, and if so, it MUST
- check whether the signature is correct.
-
- If both checks succeed, this method is successful. Note that the
- server may require additional authentications. The server MUST
- respond with SSH_MSG_USERAUTH_SUCCESS (if no more authentications are
- needed), or SSH_MSG_USERAUTH_FAILURE (if the request failed, or more
- authentications are needed).
-
- The following method-specific message numbers are used by the
- publickey authentication method.
-
- /* Key-based */
- #define SSH_MSG_USERAUTH_PK_OK 60
-
-
-
-
-Ylonen & Moffat Expires March 2, 2003 [Page 9]
-
-Internet-Draft SSH Authentication Protocol September 2002
-
-
-3.4 Password Authentication Method: password
-
- Password authentication uses the following packets. Note that a
- server MAY request the user to change the password. All
- implementations SHOULD support password authentication.
-
- byte SSH_MSG_USERAUTH_REQUEST
- string user name
- string service
- string "password"
- boolean FALSE
- string plaintext password (ISO-10646 UTF-8)
-
- Note that the password is encoded in ISO-10646 UTF-8. It is up to
- the server how it interprets the password and validates it against
- the password database. However, if the client reads the password in
- some other encoding (e.g., ISO 8859-1 (ISO Latin1)), it MUST convert
- the password to ISO-10646 UTF-8 before transmitting, and the server
- MUST convert the password to the encoding used on that system for
- passwords.
-
- Note that even though the cleartext password is transmitted in the
- packet, the entire packet is encrypted by the transport layer. Both
- the server and the client should check whether the underlying
- transport layer provides confidentiality (i.e., if encryption is
- being used). If no confidentiality is provided (none cipher),
- password authentication SHOULD be disabled. If there is no
- confidentiality or no MAC, password change SHOULD be disabled.
-
- Normally, the server responds to this message with success or
- failure. However, if the password has expired the server SHOULD
- indicate this by responding with SSH_MSG_USERAUTH_PASSWD_CHANGEREQ.
- In anycase the server MUST NOT allow an expired password to be used
- for authentication.
-
- byte SSH_MSG_USERAUTH_PASSWD_CHANGEREQ
- string prompt (ISO-10646 UTF-8)
- string language tag (as defined in [RFC3066])
-
- In this case, the client MAY continue with a different authentication
- method, or request a new password from the user and retry password
- authentication using the following message. The client MAY also send
- this message instead of the normal password authentication request
- without the server asking for it.
-
- byte SSH_MSG_USERAUTH_REQUEST
- string user name
- string service
-
-
-
-Ylonen & Moffat Expires March 2, 2003 [Page 10]
-
-Internet-Draft SSH Authentication Protocol September 2002
-
-
- string "password"
- boolean TRUE
- string plaintext old password (ISO-10646 UTF-8)
- string plaintext new password (ISO-10646 UTF-8)
-
- The server must reply to request message with
- SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE, or another
- SSH_MSG_USERAUTH_PASSWD_CHANGEREQ. The meaning of these is as
- follows:
-
- SSH_MSG_USERAUTH_SUCCESS The password has been changed, and
- authentication has been successfully completed.
-
- SSH_MSG_USERAUTH_FAILURE with partial success The password has
- been changed, but more authentications are needed.
-
- SSH_MSG_USERAUTH_FAILURE without partial success The password has
- not been changed. Either password changing was not supported, or
- the old password was bad. Note that if the server has already
- sent SSH_MSG_USERAUTH_PASSWD_CHANGEREQ, we know that it supports
- changing the password.
-
- SSH_MSG_USERAUTH_CHANGEREQ The password was not changed because
- the new password was not acceptable (e.g. too easy to guess).
-
- The following method-specific message numbers are used by the
- password authentication method.
-
- #define SSH_MSG_USERAUTH_PASSWD_CHANGEREQ 60
-
-
-3.5 Host-Based Authentication: hostbased
-
- Some sites wish to allow authentication based on the host where the
- user is coming from, and the user name on the remote host. While
- this form of authentication is not suitable for high-security sites,
- it can be very convenient in many environments. This form of
- authentication is OPTIONAL. When used, special care SHOULD be taken
- to prevent a regular user from obtaining the private host key.
-
- The client requests this form of authentication by sending the
- following message. It is similar to the UNIX "rhosts" and
- "hosts.equiv" styles of authentication, except that the identity of
- the client host is checked more rigorously.
-
- This method works by having the client send a signature created with
- the private key of the client host, which the server checks with that
- host's public key. Once the client host's identity is established,
-
-
-
-Ylonen & Moffat Expires March 2, 2003 [Page 11]
-
-Internet-Draft SSH Authentication Protocol September 2002
-
-
- authorization (but no further authentication) is performed based on
- the user names on the server and the client, and the client host
- name.
-
- byte SSH_MSG_USERAUTH_REQUEST
- string user name
- string service
- string "hostbased"
- string public key algorithm for host key
- string public host key and certificates for client host
- string client host name (FQDN; US-ASCII)
- string user name on the client host (ISO-10646 UTF-8)
- string signature
-
- Public key algorithm names for use in "public key algorithm for host
- key" are defined in the transport layer specification. The "public
- host key for client host" may include certificates.
-
- Signature is a signature with the private host key of the following
- data, in this order:
-
- string session identifier
- byte SSH_MSG_USERAUTH_REQUEST
- string user name
- string service
- string "hostbased"
- string public key algorithm for host key
- string public host key and certificates for client host
- string client host name (FQDN; US-ASCII)
- string user name on the client host(ISO-10646 UTF-8)
-
- The server MUST verify that the host key actually belongs to the
- client host named in the message, that the given user on that host is
- allowed to log in, and that the signature is a valid signature on the
- appropriate value by the given host key. The server MAY ignore the
- client user name, if it wants to authenticate only the client host.
-
- It is RECOMMENDED that whenever possible, the server perform
- additional checks to verify that the network address obtained from
- the (untrusted) network matches the given client host name. This
- makes exploiting compromised host keys more difficult. Note that
- this may require special handling for connections coming through a
- firewall.
-
-4. Security Considerations
-
- The purpose of this protocol is to perform client user
- authentication. It assumed that this runs over a secure transport
-
-
-
-Ylonen & Moffat Expires March 2, 2003 [Page 12]
-
-Internet-Draft SSH Authentication Protocol September 2002
-
-
- layer protocol, which has already authenticated the server machine,
- established an encrypted communications channel, and computed a
- unique session identifier for this session. The transport layer
- provides forward secrecy for password authentication and other
- methods that rely on secret data.
-
- Full security considerations for this protocol are provided in
- Section 8 of [SSH-ARCH]
-
-Normative
-
- [SSH-ARCH]
- Ylonen, T., "SSH Protocol Architecture", I-D
- draft-ietf-architecture-15.txt, Oct 2003.
-
- [SSH-TRANS]
- Ylonen, T., "SSH Transport Layer Protocol", I-D
- draft-ietf-transport-17.txt, Oct 2003.
-
- [SSH-USERAUTH]
- Ylonen, T., "SSH Authentication Protocol", I-D
- draft-ietf-userauth-18.txt, Oct 2003.
-
- [SSH-CONNECT]
- Ylonen, T., "SSH Connection Protocol", I-D
- draft-ietf-connect-18.txt, Oct 2003.
-
- [SSH-NUMBERS]
- Lehtinen, S. and D. Moffat, "SSH Protocol Assigned
- Numbers", I-D draft-ietf-secsh-assignednumbers-05.txt, Oct
- 2003.
-
- [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
- Requirement Levels", BCP 14, RFC 2119, March 1997.
-
-Informative
-
- [RFC3066] Alvestrand, H., "Tags for the Identification of
- Languages", BCP 47, RFC 3066, January 2001.
-
- [RFC2279] Yergeau, F., "UTF-8, a transformation format of ISO
- 10646", RFC 2279, January 1998.
-
-
-
-
-
-
-
-
-
-Ylonen & Moffat Expires March 2, 2003 [Page 13]
-
-Internet-Draft SSH Authentication Protocol September 2002
-
-
-Authors' Addresses
-
- Tatu Ylonen
- SSH Communications Security Corp
- Fredrikinkatu 42
- HELSINKI FIN-00100
- Finland
-
-
-
- Darren J. Moffat (editor)
- Sun Microsystems, Inc
- 17 Network Circle
- Menlo Park 95025
- USA
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Ylonen & Moffat Expires March 2, 2003 [Page 14]
-
-Internet-Draft SSH Authentication Protocol September 2002
-
-
-Intellectual Property Statement
-
- The IETF takes no position regarding the validity or scope of any
- intellectual property or other rights that might be claimed to
- pertain to the implementation or use of the technology described in
- this document or the extent to which any license under such rights
- might or might not be available; neither does it represent that it
- has made any effort to identify any such rights. Information on the
- IETF's procedures with respect to rights in standards-track and
- standards-related documentation can be found in BCP-11. Copies of
- claims of rights made available for publication and any assurances of
- licenses to be made available, or the result of an attempt made to
- obtain a general license or permission for the use of such
- proprietary rights by implementors or users of this specification can
- be obtained from the IETF Secretariat.
-
- The IETF invites any interested party to bring to its attention any
- copyrights, patents or patent applications, or other proprietary
- rights which may cover technology that may be required to practice
- this standard. Please address the information to the IETF Executive
- Director.
-
- The IETF has been notified of intellectual property rights claimed in
- regard to some or all of the specification contained in this
- document. For more information consult the online list of claimed
- rights.
-
-
-Full Copyright Statement
-
- Copyright (C) The Internet Society (2002). All Rights Reserved.
-
- This document and translations of it may be copied and furnished to
- others, and derivative works that comment on or otherwise explain it
- or assist in its implementation may be prepared, copied, published
- and distributed, in whole or in part, without restriction of any
- kind, provided that the above copyright notice and this paragraph are
- included on all such copies and derivative works. However, this
- document itself may not be modified in any way, such as by removing
- the copyright notice or references to the Internet Society or other
- Internet organizations, except as needed for the purpose of
- developing Internet standards in which case the procedures for
- copyrights defined in the Internet Standards process must be
- followed, or as required to translate it into languages other than
- English.
-
- The limited permissions granted above are perpetual and will not be
- revoked by the Internet Society or its successors or assignees.
-
-
-
-Ylonen & Moffat Expires March 2, 2003 [Page 15]
-
-Internet-Draft SSH Authentication Protocol September 2002
-
-
- This document and the information contained herein is provided on an
- "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
- TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
- BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
- HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
- MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
-
-
-Acknowledgment
-
- Funding for the RFC Editor function is currently provided by the
- Internet Society.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Ylonen & Moffat Expires March 2, 2003 [Page 16] \ No newline at end of file
diff --git a/lib/ssh/src/ssh.erl b/lib/ssh/src/ssh.erl
index 5bde184070..54f94acbdc 100644
--- a/lib/ssh/src/ssh.erl
+++ b/lib/ssh/src/ssh.erl
@@ -235,10 +235,27 @@ start_daemon(Host, Port, Options, Inet) ->
{error, _Reason} = Error ->
Error;
{SocketOptions, SshOptions}->
- do_start_daemon(Host, Port,[{role, server} |SshOptions] , [Inet | SocketOptions])
+ try
+ do_start_daemon(Host, Port,[{role, server} |SshOptions] , [Inet | SocketOptions])
+ catch
+ throw:bad_fd -> {error,bad_fd};
+ _C:_E -> {error,{cannot_start_daemon,_C,_E}}
+ end
end.
-do_start_daemon(Host, Port, Options, SocketOptions) ->
+do_start_daemon(Host0, Port0, Options, SocketOptions) ->
+ {Host,Port} = try
+ case proplists:get_value(fd, SocketOptions) of
+ undefined ->
+ {Host0,Port0};
+ Fd when Port0==0 ->
+ find_hostport(Fd);
+ _ ->
+ {Host0,Port0}
+ end
+ catch
+ _:_ -> throw(bad_fd)
+ end,
Profile = proplists:get_value(profile, Options, ?DEFAULT_PROFILE),
case ssh_system_sup:system_supervisor(Host, Port, Profile) of
undefined ->
@@ -272,6 +289,15 @@ do_start_daemon(Host, Port, Options, SocketOptions) ->
end
end.
+find_hostport(Fd) ->
+ %% Using internal functions inet:open/8 and inet:close/0.
+ %% Don't try this at home unless you know what you are doing!
+ {ok,S} = inet:open(Fd, {0,0,0,0}, 0, [], tcp, inet, stream, inet_tcp),
+ {ok, HostPort} = inet:sockname(S),
+ ok = inet:close(S),
+ HostPort.
+
+
handle_options(Opts) ->
try handle_option(algs_compatibility(proplists:unfold(Opts)), [], []) of
{Inet, Ssh} ->
@@ -282,32 +308,27 @@ handle_options(Opts) ->
end.
-algs_compatibility(Os) ->
+algs_compatibility(Os0) ->
%% Take care of old options 'public_key_alg' and 'pref_public_key_algs'
- comp_pk(proplists:get_value(preferred_algorithms,Os),
- proplists:get_value(pref_public_key_algs,Os),
- proplists:get_value(public_key_alg, Os),
- [{K,V} || {K,V} <- Os,
- K =/= public_key_alg,
- K =/= pref_public_key_algs]
- ).
-
-comp_pk(undefined, undefined, undefined, Os) -> Os;
-comp_pk( PrefAlgs, _, _, Os) when PrefAlgs =/= undefined -> Os;
-
-comp_pk(undefined, undefined, ssh_dsa, Os) -> comp_pk(undefined, undefined, 'ssh-dss', Os);
-comp_pk(undefined, undefined, ssh_rsa, Os) -> comp_pk(undefined, undefined, 'ssh-rsa', Os);
-comp_pk(undefined, undefined, PK, Os) ->
- PKs = [PK | ssh_transport:supported_algorithms(public_key)--[PK]],
- [{preferred_algorithms, [{public_key,PKs}] } | Os];
-
-comp_pk(undefined, PrefPKs, _, Os) when PrefPKs =/= undefined ->
- PKs = [case PK of
- ssh_dsa -> 'ssh-dss';
- ssh_rsa -> 'ssh-rsa';
- _ -> PK
- end || PK <- PrefPKs],
- [{preferred_algorithms, [{public_key,PKs}]} | Os].
+ case proplists:get_value(public_key_alg, Os0) of
+ undefined ->
+ Os0;
+ A when is_atom(A) ->
+ %% Skip public_key_alg if pref_public_key_algs is defined:
+ Os = lists:keydelete(public_key_alg, 1, Os0),
+ case proplists:get_value(pref_public_key_algs,Os) of
+ undefined when A == 'ssh-rsa' ; A==ssh_rsa ->
+ [{pref_public_key_algs,['ssh-rsa','ssh-dss']} | Os];
+ undefined when A == 'ssh-dss' ; A==ssh_dsa ->
+ [{pref_public_key_algs,['ssh-dss','ssh-rsa']} | Os];
+ undefined ->
+ throw({error, {eoptions, {public_key_alg,A} }});
+ _ ->
+ Os
+ end;
+ V ->
+ throw({error, {eoptions, {public_key_alg,V} }})
+ end.
handle_option([], SocketOptions, SshOptions) ->
@@ -336,8 +357,12 @@ handle_option([{user_passwords, _} = Opt | Rest], SocketOptions, SshOptions) ->
handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
handle_option([{pwdfun, _} = Opt | Rest], SocketOptions, SshOptions) ->
handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
-handle_option([{key_cb, _} = Opt | Rest], SocketOptions, SshOptions) ->
- handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
+handle_option([{key_cb, {Module, Options}} | Rest], SocketOptions, SshOptions) ->
+ handle_option(Rest, SocketOptions, [handle_ssh_option({key_cb, Module}),
+ handle_ssh_priv_option({key_cb_private, Options}) |
+ SshOptions]);
+handle_option([{key_cb, Module} | Rest], SocketOptions, SshOptions) ->
+ handle_option([{key_cb, {Module, []}} | Rest], SocketOptions, SshOptions);
handle_option([{keyboard_interact_fun, _} = Opt | Rest], SocketOptions, SshOptions) ->
handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
%%Backwards compatibility
@@ -374,6 +399,8 @@ handle_option([{auth_methods, _} = Opt | Rest], SocketOptions, SshOptions) ->
handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
handle_option([{auth_method_kb_interactive_data, _} = Opt | Rest], SocketOptions, SshOptions) ->
handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
+handle_option([{pref_public_key_algs, _} = Opt | Rest], SocketOptions, SshOptions) ->
+ handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
handle_option([{preferred_algorithms,_} = Opt | Rest], SocketOptions, SshOptions) ->
handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
handle_option([{dh_gex_groups,_} = Opt | Rest], SocketOptions, SshOptions) ->
@@ -485,6 +512,13 @@ handle_ssh_option({dh_gex_limits,{Min,I,Max}} = Opt) when is_integer(Min), Min>0
is_integer(Max), Max>=I ->
%% Client
Opt;
+handle_ssh_option({pref_public_key_algs, Value} = Opt) when is_list(Value), length(Value) >= 1 ->
+ case handle_user_pref_pubkey_algs(Value, []) of
+ {true, NewOpts} ->
+ {pref_public_key_algs, NewOpts};
+ _ ->
+ throw({error, {eoptions, Opt}})
+ end;
handle_ssh_option({connect_timeout, Value} = Opt) when is_integer(Value); Value == infinity ->
Opt;
handle_ssh_option({max_sessions, Value} = Opt) when is_integer(Value), Value>0 ->
@@ -511,6 +545,9 @@ handle_ssh_option({pwdfun, Value} = Opt) when is_function(Value,4) ->
Opt;
handle_ssh_option({key_cb, Value} = Opt) when is_atom(Value) ->
Opt;
+handle_ssh_option({key_cb, {CallbackMod, CallbackOptions}} = Opt) when is_atom(CallbackMod),
+ is_list(CallbackOptions) ->
+ Opt;
handle_ssh_option({keyboard_interact_fun, Value} = Opt) when is_function(Value,3) ->
Opt;
handle_ssh_option({compression, Value} = Opt) when is_atom(Value) ->
@@ -577,6 +614,9 @@ handle_ssh_option({profile, Value} = Opt) when is_atom(Value) ->
handle_ssh_option(Opt) ->
throw({error, {eoptions, Opt}}).
+handle_ssh_priv_option({key_cb_private, Value} = Opt) when is_list(Value) ->
+ Opt.
+
handle_inet_option({active, _} = Opt) ->
throw({error, {{eoptions, Opt}, "SSH has built in flow control, "
"and active is handled internally, user is not allowed"
@@ -737,3 +777,16 @@ read_moduli_file(D, I, Acc) ->
end
end.
+handle_user_pref_pubkey_algs([], Acc) ->
+ {true, lists:reverse(Acc)};
+handle_user_pref_pubkey_algs([H|T], Acc) ->
+ case lists:member(H, ?SUPPORTED_USER_KEYS) of
+ true ->
+ handle_user_pref_pubkey_algs(T, [H| Acc]);
+
+ false when H==ssh_dsa -> handle_user_pref_pubkey_algs(T, ['ssh-dss'| Acc]);
+ false when H==ssh_rsa -> handle_user_pref_pubkey_algs(T, ['ssh-rsa'| Acc]);
+
+ false ->
+ false
+ end.
diff --git a/lib/ssh/src/ssh.hrl b/lib/ssh/src/ssh.hrl
index 4ad936f742..f88098819d 100644
--- a/lib/ssh/src/ssh.hrl
+++ b/lib/ssh/src/ssh.hrl
@@ -29,11 +29,13 @@
-define(SSH_DEFAULT_PORT, 22).
-define(SSH_MAX_PACKET_SIZE, (256*1024)).
--define(SSH_LENGHT_INDICATOR_SIZE, 4).
-define(REKEY_TIMOUT, 3600000).
-define(REKEY_DATA_TIMOUT, 60000).
-define(DEFAULT_PROFILE, default).
+-define(SUPPORTED_AUTH_METHODS, "publickey,keyboard-interactive,password").
+-define(SUPPORTED_USER_KEYS, ['ssh-rsa','ssh-dss','ecdsa-sha2-nistp256','ecdsa-sha2-nistp384','ecdsa-sha2-nistp521']).
+
-define(FALSE, 0).
-define(TRUE, 1).
%% basic binary constructors
diff --git a/lib/ssh/src/ssh_acceptor.erl b/lib/ssh/src/ssh_acceptor.erl
index c5ad1d7b6c..d94dedf1bf 100644
--- a/lib/ssh/src/ssh_acceptor.erl
+++ b/lib/ssh/src/ssh_acceptor.erl
@@ -56,7 +56,12 @@ acceptor_init(Parent, Port, Address, SockOpts, Opts, AcceptTimeout) ->
error
end.
-do_socket_listen(Callback, Port, Opts) ->
+do_socket_listen(Callback, Port0, Opts) ->
+ Port =
+ case proplists:get_value(fd, Opts) of
+ undefined -> Port0;
+ _ -> 0
+ end,
case Callback:listen(Port, Opts) of
{error, nxdomain} ->
Callback:listen(Port, lists:delete(inet6, Opts));
diff --git a/lib/ssh/src/ssh_auth.erl b/lib/ssh/src/ssh_auth.erl
index 4967a2e4cd..fdbb5c152a 100644
--- a/lib/ssh/src/ssh_auth.erl
+++ b/lib/ssh/src/ssh_auth.erl
@@ -118,11 +118,16 @@ init_userauth_request_msg(#ssh{opts = Opts} = Ssh) ->
service = "ssh-connection",
method = "none",
data = <<>>},
+ Algs0 = proplists:get_value(pref_public_key_algs, Opts, ?SUPPORTED_USER_KEYS),
+ %% The following line is not strictly correct. The call returns the
+ %% supported HOST key types while we are interested in USER keys. However,
+ %% they "happens" to be the same (for now). This could change....
+ %% There is no danger as long as the set of user keys is a subset of the set
+ %% of host keys.
+ CryptoSupported = ssh_transport:supported_algorithms(public_key),
+ Algs = [A || A <- Algs0,
+ lists:member(A, CryptoSupported)],
-
- Algs = proplists:get_value(public_key,
- proplists:get_value(preferred_algorithms, Opts, []),
- ssh_transport:default_algorithms(public_key)),
Prefs = method_preference(Algs),
ssh_transport:ssh_packet(Msg, Ssh#ssh{user = User,
userauth_preference = Prefs,
diff --git a/lib/ssh/src/ssh_auth.hrl b/lib/ssh/src/ssh_auth.hrl
index 5197a42fa4..449bc4fa45 100644
--- a/lib/ssh/src/ssh_auth.hrl
+++ b/lib/ssh/src/ssh_auth.hrl
@@ -22,7 +22,6 @@
%%% Description: Ssh User Authentication Protocol
--define(SUPPORTED_AUTH_METHODS, "publickey,keyboard-interactive,password").
-define(SSH_MSG_USERAUTH_REQUEST, 50).
-define(SSH_MSG_USERAUTH_FAILURE, 51).
diff --git a/lib/ssh/src/ssh_connect.hrl b/lib/ssh/src/ssh_connect.hrl
index 6db89c5d80..9f9f3de8fa 100644
--- a/lib/ssh/src/ssh_connect.hrl
+++ b/lib/ssh/src/ssh_connect.hrl
@@ -248,6 +248,9 @@
local_id, %% local channel id
recv_window_size,
+ recv_window_pending = 0, %% Sum of window size updates that has not
+ %% yet been sent. This limits the number
+ %% of sent update msgs.
recv_packet_size,
recv_close = false,
diff --git a/lib/ssh/src/ssh_connection.erl b/lib/ssh/src/ssh_connection.erl
index 266c64fd4f..a34478732c 100644
--- a/lib/ssh/src/ssh_connection.erl
+++ b/lib/ssh/src/ssh_connection.erl
@@ -662,7 +662,7 @@ handle_msg(#ssh_msg_channel_request{recipient_channel = ChannelId,
ReplyMsg = {subsystem, ChannelId, WantReply, binary_to_list(SsName)},
try
- {ok, Pid} = start_subsytem(SsName, Connection, Channel0, ReplyMsg),
+ {ok, Pid} = start_subsystem(SsName, Connection, Channel0, ReplyMsg),
erlang:monitor(process, Pid),
Channel = Channel0#channel{user = Pid},
ssh_channel:cache_update(Cache, Channel),
@@ -1017,7 +1017,7 @@ start_cli(#connection{options = Options,
sub_system_supervisor = SubSysSup}, ChannelId) ->
start_channel(CbModule, ChannelId, Args, SubSysSup, Exec, Options).
-start_subsytem(BinName, #connection{options = Options,
+start_subsystem(BinName, #connection{options = Options,
sub_system_supervisor = SubSysSup},
#channel{local_id = ChannelId}, _ReplyMsg) ->
Name = binary_to_list(BinName),
diff --git a/lib/ssh/src/ssh_connection_handler.erl b/lib/ssh/src/ssh_connection_handler.erl
index a2d1b5b810..f082db136c 100644
--- a/lib/ssh/src/ssh_connection_handler.erl
+++ b/lib/ssh/src/ssh_connection_handler.erl
@@ -433,6 +433,12 @@ key_exchange(#ssh_msg_kex_dh_gex_request{} = Msg,
send_msg(GexGroup, State),
{next_state, key_exchange_dh_gex_init, next_packet(State#state{ssh_params = Ssh})};
+key_exchange(#ssh_msg_kex_dh_gex_request_old{} = Msg,
+ #state{ssh_params = #ssh{role = server} = Ssh0} = State) ->
+ {ok, GexGroup, Ssh} = ssh_transport:handle_kex_dh_gex_request(Msg, Ssh0),
+ send_msg(GexGroup, State),
+ {next_state, key_exchange_dh_gex_init, next_packet(State#state{ssh_params = Ssh})};
+
key_exchange(#ssh_msg_kex_dh_gex_group{} = Msg,
#state{ssh_params = #ssh{role = client} = Ssh0} = State) ->
{ok, KexGexInit, Ssh} = ssh_transport:handle_kex_dh_gex_group(Msg, Ssh0),
@@ -731,13 +737,28 @@ handle_event({adjust_window, ChannelId, Bytes}, StateName,
#connection{channel_cache = Cache}} = State0) ->
State =
case ssh_channel:cache_lookup(Cache, ChannelId) of
- #channel{recv_window_size = WinSize, remote_id = Id} = Channel ->
- ssh_channel:cache_update(Cache, Channel#channel{recv_window_size =
- WinSize + Bytes}),
- Msg = ssh_connection:channel_adjust_window_msg(Id, Bytes),
+ #channel{recv_window_size = WinSize,
+ recv_window_pending = Pending,
+ recv_packet_size = PktSize} = Channel
+ when (WinSize-Bytes) >= 2*PktSize ->
+ %% The peer can send at least two more *full* packet, no hurry.
+ ssh_channel:cache_update(Cache,
+ Channel#channel{recv_window_pending = Pending + Bytes}),
+ State0;
+
+ #channel{recv_window_size = WinSize,
+ recv_window_pending = Pending,
+ remote_id = Id} = Channel ->
+ %% Now we have to update the window - we can't receive so many more pkts
+ ssh_channel:cache_update(Cache,
+ Channel#channel{recv_window_size =
+ WinSize + Bytes + Pending,
+ recv_window_pending = 0}),
+ Msg = ssh_connection:channel_adjust_window_msg(Id, Bytes + Pending),
send_replies([{connection_reply, Msg}], State0);
- undefined ->
- State0
+
+ undefined ->
+ State0
end,
{next_state, StateName, next_packet(State)};
@@ -970,57 +991,55 @@ handle_info({Protocol, Socket, Info}, hello,
transport_protocol = Protocol} = State) ->
event({info_line, Info}, hello, State);
-handle_info({Protocol, Socket, Data}, Statename,
- #state{socket = Socket,
- transport_protocol = Protocol,
- ssh_params = #ssh{decrypt_block_size = BlockSize,
- recv_mac_size = MacSize} = Ssh0,
- decoded_data_buffer = <<>>,
- encoded_data_buffer = EncData0} = State0) ->
-
- %% Implementations SHOULD decrypt the length after receiving the
- %% first 8 (or cipher block size, whichever is larger) bytes of a
- %% packet. (RFC 4253: Section 6 - Binary Packet Protocol)
- case size(EncData0) + size(Data) >= erlang:max(8, BlockSize) of
- true ->
- {Ssh, SshPacketLen, DecData, EncData} =
-
- ssh_transport:decrypt_first_block(<<EncData0/binary,
- Data/binary>>, Ssh0),
- case SshPacketLen > ?SSH_MAX_PACKET_SIZE of
- true ->
- DisconnectMsg =
- #ssh_msg_disconnect{code =
- ?SSH_DISCONNECT_PROTOCOL_ERROR,
- description = "Bad packet length "
- ++ integer_to_list(SshPacketLen),
- language = "en"},
- handle_disconnect(DisconnectMsg, State0);
- false ->
- RemainingSshPacketLen =
- (SshPacketLen + ?SSH_LENGHT_INDICATOR_SIZE) -
- BlockSize + MacSize,
- State = State0#state{ssh_params = Ssh},
- handle_ssh_packet_data(RemainingSshPacketLen,
- DecData, EncData, Statename,
- State)
- end;
- false ->
- {next_state, Statename,
- next_packet(State0#state{encoded_data_buffer =
- <<EncData0/binary, Data/binary>>})}
- end;
-
-handle_info({Protocol, Socket, Data}, Statename,
+handle_info({Protocol, Socket, Data}, StateName,
#state{socket = Socket,
transport_protocol = Protocol,
- decoded_data_buffer = DecData,
- encoded_data_buffer = EncData,
- undecoded_packet_length = Len} =
- State) when is_integer(Len) ->
- handle_ssh_packet_data(Len, DecData, <<EncData/binary, Data/binary>>,
- Statename, State);
+ ssh_params = Ssh0,
+ decoded_data_buffer = DecData0,
+ encoded_data_buffer = EncData0,
+ undecoded_packet_length = RemainingSshPacketLen0} = State0) ->
+ Encoded = <<EncData0/binary, Data/binary>>,
+ try ssh_transport:handle_packet_part(DecData0, Encoded, RemainingSshPacketLen0, Ssh0)
+ of
+ {get_more, DecBytes, EncDataRest, RemainingSshPacketLen, Ssh1} ->
+ {next_state, StateName,
+ next_packet(State0#state{encoded_data_buffer = EncDataRest,
+ decoded_data_buffer = DecBytes,
+ undecoded_packet_length = RemainingSshPacketLen,
+ ssh_params = Ssh1})};
+ {decoded, MsgBytes, EncDataRest, Ssh1} ->
+ generate_event(MsgBytes, StateName,
+ State0#state{ssh_params = Ssh1,
+ %% Important to be set for
+ %% next_packet
+%%% FIXME: the following three seem to always be set in generate_event!
+ decoded_data_buffer = <<>>,
+ undecoded_packet_length = undefined,
+ encoded_data_buffer = EncDataRest},
+ EncDataRest);
+ {bad_mac, Ssh1} ->
+ DisconnectMsg =
+ #ssh_msg_disconnect{code = ?SSH_DISCONNECT_PROTOCOL_ERROR,
+ description = "Bad mac",
+ language = ""},
+ handle_disconnect(DisconnectMsg, State0#state{ssh_params=Ssh1});
+ {error, {exceeds_max_size,PacketLen}} ->
+ DisconnectMsg =
+ #ssh_msg_disconnect{code = ?SSH_DISCONNECT_PROTOCOL_ERROR,
+ description = "Bad packet length "
+ ++ integer_to_list(PacketLen),
+ language = ""},
+ handle_disconnect(DisconnectMsg, State0)
+ catch
+ _:_ ->
+ DisconnectMsg =
+ #ssh_msg_disconnect{code = ?SSH_DISCONNECT_PROTOCOL_ERROR,
+ description = "Bad packet",
+ language = ""},
+ handle_disconnect(DisconnectMsg, State0)
+ end;
+
handle_info({CloseTag, _Socket}, _StateName,
#state{transport_close_tag = CloseTag,
ssh_params = #ssh{role = _Role, opts = _Opts}} = State) ->
@@ -1098,7 +1117,7 @@ handle_info(UnexpectedMessage, StateName, #state{opts = Opts,
terminate(normal, _, #state{transport_cb = Transport,
connection_state = Connection,
socket = Socket}) ->
- terminate_subsytem(Connection),
+ terminate_subsystem(Connection),
(catch Transport:close(Socket)),
ok;
@@ -1127,7 +1146,7 @@ terminate({shutdown, _}, StateName, State) ->
terminate(Reason, StateName, #state{ssh_params = Ssh0, starter = _Pid,
connection_state = Connection} = State) ->
- terminate_subsytem(Connection),
+ terminate_subsystem(Connection),
log_error(Reason),
DisconnectMsg =
#ssh_msg_disconnect{code = ?SSH_DISCONNECT_BY_APPLICATION,
@@ -1138,10 +1157,10 @@ terminate(Reason, StateName, #state{ssh_params = Ssh0, starter = _Pid,
terminate(normal, StateName, State#state{ssh_params = Ssh}).
-terminate_subsytem(#connection{system_supervisor = SysSup,
+terminate_subsystem(#connection{system_supervisor = SysSup,
sub_system_supervisor = SubSysSup}) when is_pid(SubSysSup) ->
ssh_system_sup:stop_subsystem(SysSup, SubSysSup);
-terminate_subsytem(_) ->
+terminate_subsystem(_) ->
ok.
format_status(normal, [_, State]) ->
@@ -1389,44 +1408,54 @@ generate_event(<<?BYTE(Byte), _/binary>> = Msg, StateName,
Byte == ?SSH_MSG_CHANNEL_REQUEST;
Byte == ?SSH_MSG_CHANNEL_SUCCESS;
Byte == ?SSH_MSG_CHANNEL_FAILURE ->
- ConnectionMsg = ssh_message:decode(Msg),
- State1 = generate_event_new_state(State0, EncData),
- try ssh_connection:handle_msg(ConnectionMsg, Connection0, Role) of
- {{replies, Replies0}, Connection} ->
- if StateName == connected ->
- Replies = Replies0,
- State2 = State1;
- true ->
- {ConnReplies, Replies} =
- lists:splitwith(fun not_connected_filter/1, Replies0),
- Q = State1#state.event_queue ++ ConnReplies,
- State2 = State1#state{ event_queue = Q }
- end,
- State = send_replies(Replies, State2#state{connection_state = Connection}),
- {next_state, StateName, next_packet(State)};
- {noreply, Connection} ->
- {next_state, StateName, next_packet(State1#state{connection_state = Connection})};
- {disconnect, {_, Reason}, {{replies, Replies}, Connection}} when
- Role == client andalso ((StateName =/= connected) and (not Renegotiation)) ->
- State = send_replies(Replies, State1#state{connection_state = Connection}),
- User ! {self(), not_connected, Reason},
- {stop, {shutdown, normal},
- next_packet(State#state{connection_state = Connection})};
- {disconnect, _Reason, {{replies, Replies}, Connection}} ->
- State = send_replies(Replies, State1#state{connection_state = Connection}),
- {stop, {shutdown, normal}, State#state{connection_state = Connection}}
+ try
+ ssh_message:decode(Msg)
+ of
+ ConnectionMsg ->
+ State1 = generate_event_new_state(State0, EncData),
+ try ssh_connection:handle_msg(ConnectionMsg, Connection0, Role) of
+ {{replies, Replies0}, Connection} ->
+ if StateName == connected ->
+ Replies = Replies0,
+ State2 = State1;
+ true ->
+ {ConnReplies, Replies} =
+ lists:splitwith(fun not_connected_filter/1, Replies0),
+ Q = State1#state.event_queue ++ ConnReplies,
+ State2 = State1#state{ event_queue = Q }
+ end,
+ State = send_replies(Replies, State2#state{connection_state = Connection}),
+ {next_state, StateName, next_packet(State)};
+ {noreply, Connection} ->
+ {next_state, StateName, next_packet(State1#state{connection_state = Connection})};
+ {disconnect, {_, Reason}, {{replies, Replies}, Connection}} when
+ Role == client andalso ((StateName =/= connected) and (not Renegotiation)) ->
+ State = send_replies(Replies, State1#state{connection_state = Connection}),
+ User ! {self(), not_connected, Reason},
+ {stop, {shutdown, normal},
+ next_packet(State#state{connection_state = Connection})};
+ {disconnect, _Reason, {{replies, Replies}, Connection}} ->
+ State = send_replies(Replies, State1#state{connection_state = Connection}),
+ {stop, {shutdown, normal}, State#state{connection_state = Connection}}
+ catch
+ _:Error ->
+ {disconnect, _Reason, {{replies, Replies}, Connection}} =
+ ssh_connection:handle_msg(
+ #ssh_msg_disconnect{code = ?SSH_DISCONNECT_BY_APPLICATION,
+ description = "Internal error",
+ language = "en"}, Connection0, Role),
+ State = send_replies(Replies, State1#state{connection_state = Connection}),
+ {stop, {shutdown, Error}, State#state{connection_state = Connection}}
+ end
+
catch
- _:Error ->
- {disconnect, _Reason, {{replies, Replies}, Connection}} =
- ssh_connection:handle_msg(
- #ssh_msg_disconnect{code = ?SSH_DISCONNECT_BY_APPLICATION,
- description = "Internal error",
- language = "en"}, Connection0, Role),
- State = send_replies(Replies, State1#state{connection_state = Connection}),
- {stop, {shutdown, Error}, State#state{connection_state = Connection}}
+ _:_ ->
+ handle_disconnect(
+ #ssh_msg_disconnect{code = ?SSH_DISCONNECT_PROTOCOL_ERROR,
+ description = "Bad packet received",
+ language = ""}, State0)
end;
-
generate_event(Msg, StateName, State0, EncData) ->
try
Event = ssh_message:decode(set_prefix_if_trouble(Msg,State0)),
@@ -1631,57 +1660,6 @@ after_new_keys_events({connection_reply, _Data} = Reply, {StateName, State}) ->
NewState = send_replies([Reply], State),
{next_state, StateName, NewState}.
-handle_ssh_packet_data(RemainingSshPacketLen, DecData, EncData, StateName,
- State) ->
- EncSize = size(EncData),
- case RemainingSshPacketLen > EncSize of
- true ->
- {next_state, StateName,
- next_packet(State#state{decoded_data_buffer = DecData,
- encoded_data_buffer = EncData,
- undecoded_packet_length =
- RemainingSshPacketLen})};
- false ->
- handle_ssh_packet(RemainingSshPacketLen, StateName,
- State#state{decoded_data_buffer = DecData,
- encoded_data_buffer = EncData})
-
- end.
-
-handle_ssh_packet(Length, StateName, #state{decoded_data_buffer = DecData0,
- encoded_data_buffer = EncData0,
- ssh_params = Ssh0,
- transport_protocol = _Protocol,
- socket = _Socket} = State0) ->
- try
- {Ssh1, DecData, EncData, Mac} =
- ssh_transport:unpack(EncData0, Length, Ssh0),
- SshPacket = <<DecData0/binary, DecData/binary>>,
- case ssh_transport:is_valid_mac(Mac, SshPacket, Ssh1) of
- true ->
- PacketData = ssh_transport:msg_data(SshPacket),
- {Ssh1, Msg} = ssh_transport:decompress(Ssh1, PacketData),
- generate_event(Msg, StateName,
- State0#state{ssh_params = Ssh1,
- %% Important to be set for
- %% next_packet
- decoded_data_buffer = <<>>},
- EncData);
- false ->
- DisconnectMsg =
- #ssh_msg_disconnect{code = ?SSH_DISCONNECT_PROTOCOL_ERROR,
- description = "Bad mac",
- language = "en"},
- handle_disconnect(DisconnectMsg, State0)
- end
- catch _:_ ->
- Disconnect =
- #ssh_msg_disconnect{code = ?SSH_DISCONNECT_PROTOCOL_ERROR,
- description = "Bad input",
- language = "en"},
- handle_disconnect(Disconnect, State0)
- end.
-
handle_disconnect(DisconnectMsg, State) ->
handle_disconnect(own, DisconnectMsg, State).
diff --git a/lib/ssh/src/ssh_file.erl b/lib/ssh/src/ssh_file.erl
index c087ce14d7..3e066c453d 100644
--- a/lib/ssh/src/ssh_file.erl
+++ b/lib/ssh/src/ssh_file.erl
@@ -221,9 +221,11 @@ do_lookup_host_key(KeyToMatch, Host, Alg, Opts) ->
{ok, Fd} ->
Res = lookup_host_key_fd(Fd, KeyToMatch, Host, Alg),
file:close(Fd),
- {ok, Res};
- {error, enoent} -> {error, not_found};
- Error -> Error
+ Res;
+ {error, enoent} ->
+ {error, not_found};
+ Error ->
+ Error
end.
identity_key_filename('ssh-dss' ) -> "id_dsa";
@@ -242,6 +244,9 @@ lookup_host_key_fd(Fd, KeyToMatch, Host, KeyType) ->
case io:get_line(Fd, '') of
eof ->
{error, not_found};
+ {error,Error} ->
+ %% Rare... For example NFS errors
+ {error,Error};
Line ->
case ssh_decode_line(Line, known_hosts) of
[{Key, Attributes}] ->
@@ -262,7 +267,7 @@ handle_host(Fd, KeyToMatch, Host, HostList, Key, KeyType) ->
Host1 = host_name(Host),
case lists:member(Host1, HostList) andalso key_match(Key, KeyType) of
true when KeyToMatch == Key ->
- Key;
+ {ok,Key};
_ ->
lookup_host_key_fd(Fd, KeyToMatch, Host, KeyType)
end.
@@ -309,6 +314,9 @@ lookup_user_key_fd(Fd, Key) ->
case io:get_line(Fd, '') of
eof ->
{error, not_found};
+ {error,Error} ->
+ %% Rare... For example NFS errors
+ {error,Error};
Line ->
case ssh_decode_line(Line, auth_keys) of
[{AuthKey, _}] ->
@@ -328,8 +336,18 @@ is_auth_key(Key, Key) ->
is_auth_key(_,_) ->
false.
-default_user_dir()->
- {ok,[[Home|_]]} = init:get_argument(home),
+
+default_user_dir() ->
+ try
+ default_user_dir(os:getenv("HOME"))
+ catch
+ _:_ ->
+ default_user_dir(init:get_argument(home))
+ end.
+
+default_user_dir({ok,[[Home|_]]}) ->
+ default_user_dir(Home);
+default_user_dir(Home) when is_list(Home) ->
UserDir = filename:join(Home, ".ssh"),
ok = filelib:ensure_dir(filename:join(UserDir, "dummy")),
{ok,Info} = file:read_file_info(UserDir),
diff --git a/lib/ssh/src/ssh_sftpd.erl b/lib/ssh/src/ssh_sftpd.erl
index a6549f1c73..819cba697e 100644
--- a/lib/ssh/src/ssh_sftpd.erl
+++ b/lib/ssh/src/ssh_sftpd.erl
@@ -30,6 +30,7 @@
-include("ssh.hrl").
-include("ssh_xfer.hrl").
+-include("ssh_connect.hrl"). %% For ?DEFAULT_PACKET_SIZE and ?DEFAULT_WINDOW_SIZE
%%--------------------------------------------------------------------
%% External exports
@@ -47,6 +48,7 @@
file_handler, % atom() - callback module
file_state, % state for the file callback module
max_files, % integer >= 0 max no files sent during READDIR
+ options, % from the subsystem declaration
handles % list of open handles
%% handle is either {<int>, directory, {Path, unread|eof}} or
%% {<int>, file, {Path, IoDevice}}
@@ -121,6 +123,7 @@ init(Options) ->
MaxLength = proplists:get_value(max_files, Options, 0),
Vsn = proplists:get_value(sftpd_vsn, Options, 5),
{ok, State#state{cwd = CWD, root = Root, max_files = MaxLength,
+ options = Options,
handles = [], pending = <<>>,
xf = #ssh_xfer{vsn = Vsn, ext = []}}}.
@@ -164,7 +167,9 @@ handle_ssh_msg({ssh_cm, _, {exit_status, ChannelId, Status}}, State) ->
%% Description: Handles other messages
%%--------------------------------------------------------------------
handle_msg({ssh_channel_up, ChannelId, ConnectionManager},
- #state{xf =Xf} = State) ->
+ #state{xf = Xf,
+ options = Options} = State) ->
+ maybe_increase_recv_window(ConnectionManager, ChannelId, Options),
{ok, State#state{xf = Xf#ssh_xfer{cm = ConnectionManager,
channel = ChannelId}}}.
@@ -934,3 +939,18 @@ rename(Path, Path2, ReqId, State0) ->
{Status, FS1} = FileMod:rename(Path, Path2, FS0),
State1 = State0#state{file_state = FS1},
send_status(Status, ReqId, State1).
+
+
+maybe_increase_recv_window(ConnectionManager, ChannelId, Options) ->
+ WantedRecvWindowSize =
+ proplists:get_value(recv_window_size, Options, 1000000),
+ NumPkts = WantedRecvWindowSize div ?DEFAULT_PACKET_SIZE,
+ Increment = NumPkts*?DEFAULT_PACKET_SIZE - ?DEFAULT_WINDOW_SIZE,
+
+ if
+ Increment > 0 ->
+ ssh_connection:adjust_window(ConnectionManager, ChannelId,
+ Increment);
+ Increment =< 0 ->
+ do_nothing
+ end.
diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl
index d61fc76c0a..18037b8461 100644
--- a/lib/ssh/src/ssh_transport.erl
+++ b/lib/ssh/src/ssh_transport.erl
@@ -31,10 +31,10 @@
-include("ssh.hrl").
-export([versions/2, hello_version_msg/1]).
--export([next_seqnum/1, decrypt_first_block/2, decrypt_blocks/3,
+-export([next_seqnum/1,
supported_algorithms/0, supported_algorithms/1,
default_algorithms/0, default_algorithms/1,
- is_valid_mac/3,
+ handle_packet_part/4,
handle_hello_version/1,
key_exchange_init_msg/1,
key_init/3, new_keys_message/1,
@@ -45,9 +45,13 @@
handle_kex_ecdh_init/2,
handle_kex_ecdh_reply/2,
extract_public_key/1,
- unpack/3, decompress/2, ssh_packet/2, pack/2, pack/3, msg_data/1,
+ ssh_packet/2, pack/2,
sign/3, verify/4]).
+%%% For test suites
+-export([pack/3]).
+-export([decompress/2, decrypt_blocks/3, is_valid_mac/3 ]). % FIXME: remove
+
%%%----------------------------------------------------------------------------
%%%
%%% There is a difference between supported and default algorithms. The
@@ -66,10 +70,15 @@ default_algorithms() -> [{K,default_algorithms(K)} || K <- algo_classes()].
algo_classes() -> [kex, public_key, cipher, mac, compression].
-%% default_algorithms(kex) -> % Example of how to disable an algorithm
-%% supported_algorithms(kex, ['ecdh-sha2-nistp521']);
+
+default_algorithms(cipher) ->
+ supported_algorithms(cipher, same(['AEAD_AES_128_GCM',
+ 'AEAD_AES_256_GCM']));
+default_algorithms(mac) ->
+ supported_algorithms(mac, same(['AEAD_AES_128_GCM',
+ 'AEAD_AES_256_GCM']));
default_algorithms(Alg) ->
- supported_algorithms(Alg).
+ supported_algorithms(Alg, []).
supported_algorithms() -> [{K,supported_algorithms(K)} || K <- algo_classes()].
@@ -97,19 +106,25 @@ supported_algorithms(public_key) ->
supported_algorithms(cipher) ->
same(
select_crypto_supported(
- [{'aes256-ctr', [{ciphers,{aes_ctr,256}}]},
- {'aes192-ctr', [{ciphers,{aes_ctr,192}}]},
- {'aes128-ctr', [{ciphers,{aes_ctr,128}}]},
- {'aes128-cbc', [{ciphers,aes_cbc128}]},
- {'3des-cbc', [{ciphers,des3_cbc}]}
+ [{'aes256-ctr', [{ciphers,{aes_ctr,256}}]},
+ {'aes192-ctr', [{ciphers,{aes_ctr,192}}]},
+ {'aes128-ctr', [{ciphers,{aes_ctr,128}}]},
+ {'aes128-cbc', [{ciphers,aes_cbc128}]},
+ {'[email protected]', [{ciphers,{aes_gcm,128}}]},
+ {'[email protected]', [{ciphers,{aes_gcm,256}}]},
+ {'AEAD_AES_128_GCM', [{ciphers,{aes_gcm,128}}]},
+ {'AEAD_AES_256_GCM', [{ciphers,{aes_gcm,256}}]},
+ {'3des-cbc', [{ciphers,des3_cbc}]}
]
));
supported_algorithms(mac) ->
same(
select_crypto_supported(
- [{'hmac-sha2-256', [{hashs,sha256}]},
- {'hmac-sha2-512', [{hashs,sha512}]},
- {'hmac-sha1', [{hashs,sha}]}
+ [{'hmac-sha2-256', [{hashs,sha256}]},
+ {'hmac-sha2-512', [{hashs,sha512}]},
+ {'hmac-sha1', [{hashs,sha}]},
+ {'AEAD_AES_128_GCM', [{ciphers,{aes_gcm,128}}]},
+ {'AEAD_AES_256_GCM', [{ciphers,{aes_gcm,256}}]}
]
));
supported_algorithms(compression) ->
@@ -118,46 +133,6 @@ supported_algorithms(compression) ->
'zlib'
]).
-%% Dialyzer complains when not called...supported_algorithms(Key, [{client2server,BL1},{server2client,BL2}]) ->
-%% Dialyzer complains when not called... [{client2server,As1},{server2client,As2}] = supported_algorithms(Key),
-%% Dialyzer complains when not called... [{client2server,As1--BL1},{server2client,As2--BL2}];
-%% Dialyzer complains when not called...supported_algorithms(Key, BlackList) ->
-%% Dialyzer complains when not called... supported_algorithms(Key) -- BlackList.
-
-select_crypto_supported(L) ->
- Sup = [{ec_curve,crypto_supported_curves()} | crypto:supports()],
- [Name || {Name,CryptoRequires} <- L,
- crypto_supported(CryptoRequires, Sup)].
-
-crypto_supported_curves() ->
- try crypto:ec_curves()
- catch _:_ -> []
- end.
-
-crypto_supported(Conditions, Supported) ->
- lists:all( fun({Tag,CryptoName}) when is_atom(CryptoName) ->
- crypto_name_supported(Tag,CryptoName,Supported);
- ({Tag,{Name=aes_ctr,Len}}) when is_integer(Len) ->
- crypto_name_supported(Tag,Name,Supported) andalso
- ctr_len_supported(Name,Len)
- end, Conditions).
-
-crypto_name_supported(Tag, CryptoName, Supported) ->
- lists:member(CryptoName, proplists:get_value(Tag,Supported,[])).
-
-ctr_len_supported(Name, Len) ->
- try
- crypto:stream_encrypt(crypto:stream_init(Name, <<0:Len>>, <<0:128>>), <<"">>)
- of
- {_,X} -> is_binary(X)
- catch
- _:_ -> false
- end.
-
-
-same(Algs) -> [{client2server,Algs}, {server2client,Algs}].
-
-
%%%----------------------------------------------------------------------------
versions(client, Options)->
Vsn = proplists:get_value(vsn, Options, ?DEFAULT_CLIENT_VERSION),
@@ -196,12 +171,6 @@ hello_version_msg(Data) ->
next_seqnum(SeqNum) ->
(SeqNum + 1) band 16#ffffffff.
-decrypt_first_block(Bin, #ssh{decrypt_block_size = BlockSize} = Ssh0) ->
- <<EncBlock:BlockSize/binary, EncData/binary>> = Bin,
- {Ssh, <<?UINT32(PacketLen), _/binary>> = DecData} =
- decrypt(Ssh0, EncBlock),
- {Ssh, PacketLen, DecData, EncData}.
-
decrypt_blocks(Bin, Length, Ssh0) ->
<<EncBlocks:Length/binary, EncData/binary>> = Bin,
{Ssh, DecData} = decrypt(Ssh0, EncBlocks),
@@ -464,6 +433,40 @@ handle_kex_dh_gex_request(#ssh_msg_kex_dh_gex_request{min = Min0,
language = ""})
end;
+handle_kex_dh_gex_request(#ssh_msg_kex_dh_gex_request_old{n = NBits},
+ Ssh0=#ssh{opts=Opts}) ->
+ %% server
+ %%
+ %% This message was in the draft-00 of rfc4419
+ %% (https://tools.ietf.org/html/draft-ietf-secsh-dh-group-exchange-00)
+ %% In later drafts and the rfc is "is used for backward compatibility".
+ %% Unfortunatly the rfc does not specify how to treat the parameter n
+ %% if there is no group of that modulus length :(
+ %% The draft-00 however specifies that n is the "... number of bits
+ %% the subgroup should have at least".
+ %% Further, it says that "Servers and clients SHOULD support groups
+ %% with a modulus length of k bits, where 1024 <= k <= 8192."
+ %%
+ Min0 = NBits,
+ Max0 = 8192,
+ {Min, Max} = adjust_gex_min_max(Min0, Max0, Opts),
+ case public_key:dh_gex_group(Min, NBits, Max,
+ proplists:get_value(dh_gex_groups,Opts)) of
+ {ok, {_Sz, {G,P}}} ->
+ {Public, Private} = generate_key(dh, [P,G]),
+ {SshPacket, Ssh} =
+ ssh_packet(#ssh_msg_kex_dh_gex_group{p = P, g = G}, Ssh0),
+ {ok, SshPacket,
+ Ssh#ssh{keyex_key = {{Private, Public}, {G, P}},
+ keyex_info = {-1, -1, NBits} % flag for kex_h hash calc
+ }};
+ {error,_} ->
+ throw(#ssh_msg_disconnect{
+ code = ?SSH_DISCONNECT_PROTOCOL_ERROR,
+ description = "No possible diffie-hellman-group-exchange group found",
+ language = ""})
+ end;
+
handle_kex_dh_gex_request(_, _) ->
throw({{error,bad_ssh_msg_kex_dh_gex_request},
#ssh_msg_disconnect{
@@ -593,10 +596,11 @@ handle_kex_ecdh_init(#ssh_msg_kex_ecdh_init{q_c = PeerPublic},
Ssh0 = #ssh{algorithms = #alg{kex=Kex}}) ->
%% at server
Curve = ecdh_curve(Kex),
- case ecdh_validate_public_key(PeerPublic, Curve) of
- true ->
- {MyPublic, MyPrivate} = generate_key(ecdh, Curve),
- K = compute_key(ecdh, PeerPublic, MyPrivate, Curve),
+ {MyPublic, MyPrivate} = generate_key(ecdh, Curve),
+ try
+ compute_key(ecdh, PeerPublic, MyPrivate, Curve)
+ of
+ K ->
MyPrivHostKey = get_host_key(Ssh0),
MyPubHostKey = extract_public_key(MyPrivHostKey),
H = kex_h(Ssh0, Curve, MyPubHostKey, PeerPublic, MyPublic, K),
@@ -609,9 +613,9 @@ handle_kex_ecdh_init(#ssh_msg_kex_ecdh_init{q_c = PeerPublic},
{ok, SshPacket, Ssh1#ssh{keyex_key = {{MyPublic,MyPrivate},Curve},
shared_secret = K,
exchanged_hash = H,
- session_id = sid(Ssh1, H)}};
-
- false ->
+ session_id = sid(Ssh1, H)}}
+ catch
+ _:_ ->
throw({{error,invalid_peer_public_key},
#ssh_msg_disconnect{
code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
@@ -626,9 +630,10 @@ handle_kex_ecdh_reply(#ssh_msg_kex_ecdh_reply{public_host_key = PeerPubHostKey,
#ssh{keyex_key = {{MyPublic,MyPrivate}, Curve}} = Ssh0
) ->
%% at client
- case ecdh_validate_public_key(PeerPublic, Curve) of
- true ->
- K = compute_key(ecdh, PeerPublic, MyPrivate, Curve),
+ try
+ compute_key(ecdh, PeerPublic, MyPrivate, Curve)
+ of
+ K ->
H = kex_h(Ssh0, Curve, PeerPubHostKey, MyPublic, PeerPublic, K),
case verify_host_key(Ssh0, PeerPubHostKey, H, H_SIG) of
ok ->
@@ -643,9 +648,9 @@ handle_kex_ecdh_reply(#ssh_msg_kex_ecdh_reply{public_host_key = PeerPubHostKey,
description = "Key exchange failed",
language = ""}
})
- end;
-
- false ->
+ end
+ catch
+ _:_ ->
throw({{error,invalid_peer_public_key},
#ssh_msg_disconnect{
code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
@@ -656,62 +661,6 @@ handle_kex_ecdh_reply(#ssh_msg_kex_ecdh_reply{public_host_key = PeerPubHostKey,
%%%----------------------------------------------------------------
-%%%
-%%% Standards for Efficient Cryptography Group, "Elliptic Curve Cryptography", SEC 1
-%%% Section 3.2.2.1
-%%%
-
-ecdh_validate_public_key(Key, Curve) ->
- case key_size(Curve) of
- undefined ->
- false;
-
- Sz ->
- case dec_key(Key, Sz) of
- {ok,Q} ->
- case crypto:ec_curve(Curve) of
- {{prime_field,P}, {A, B, _Seed},
- _P0Bin, _OrderBin, _CoFactorBin} ->
- on_curve(Q, bin2int(A), bin2int(B), bin2int(P))
- end;
-
- {error,compressed_not_implemented} -> % Be a bit generous...
- true;
-
- _Error ->
- false
- end
- end.
-
-
-on_curve({X,Y}, A, B, P) when 0 =< X,X =< (P-1),
- 0 =< Y,Y =< (P-1) ->
- %% Section 3.2.2.1, point 2
- (Y*Y) rem P == (X*X*X + A*X + B) rem P;
-on_curve(_, _, _, _) ->
- false.
-
-
-bin2int(B) ->
- Sz = erlang:bit_size(B),
- <<I:Sz/big-unsigned-integer>> = B,
- I.
-
-key_size(secp256r1) -> 256;
-key_size(secp384r1) -> 384;
-key_size(secp521r1) -> 528; % Round 521 up to closest 8-bits.
-key_size(_) -> undefined.
-
-
-dec_key(Key, NBits) ->
- Size = 8 + 2*NBits,
- case <<Key:Size>> of
- <<4:8, X:NBits, Y:NBits>> -> {ok,{X,Y}};
- <<4:8, _/binary>> -> {error,bad_format};
- _ -> {error,compressed_not_implemented}
- end.
-
-%%%----------------------------------------------------------------
handle_new_keys(#ssh_msg_newkeys{}, Ssh0) ->
try install_alg(Ssh0) of
#ssh{} = Ssh ->
@@ -811,8 +760,12 @@ known_host_key(#ssh{opts = Opts, key_cb = Mod, peer = Peer} = Ssh,
%% The first algorithm in each list MUST be the preferred (guessed)
%% algorithm. Each string MUST contain at least one algorithm name.
select_algorithm(Role, Client, Server) ->
- {Encrypt, Decrypt} = select_encrypt_decrypt(Role, Client, Server),
- {SendMac, RecvMac} = select_send_recv_mac(Role, Client, Server),
+ {Encrypt0, Decrypt0} = select_encrypt_decrypt(Role, Client, Server),
+ {SendMac0, RecvMac0} = select_send_recv_mac(Role, Client, Server),
+
+ {Encrypt, SendMac} = aead_gcm_simultan(Encrypt0, SendMac0),
+ {Decrypt, RecvMac} = aead_gcm_simultan(Decrypt0, RecvMac0),
+
{Compression, Decompression} =
select_compression_decompression(Role, Client, Server),
@@ -843,6 +796,38 @@ select_algorithm(Role, Client, Server) ->
s_lng = S_Lng},
{ok, Alg}.
+
+%%% It is an agreed problem with RFC 5674 that if the selection is
+%%% Cipher = AEAD_AES_x_GCM and
+%%% Mac = AEAD_AES_y_GCM (where x =/= y)
+%%% then it is undefined what length should be selected.
+%%%
+%%% If only one of the two lengths (128,256) is available, I claim that
+%%% there is no such ambiguity.
+
+%%% From https://anongit.mindrot.org/openssh.git/plain/PROTOCOL
+%%% (read Nov 20, 2015)
+%%% 1.6 transport: AES-GCM
+%%%
+%%% OpenSSH supports the AES-GCM algorithm as specified in RFC 5647.
+%%% Because of problems with the specification of the key exchange
+%%% the behaviour of OpenSSH differs from the RFC as follows:
+%%%
+%%% AES-GCM is only negotiated as the cipher algorithms
+%%% "[email protected]" or "[email protected]" and never as
+%%% an MAC algorithm. Additionally, if AES-GCM is selected as the cipher
+%%% the exchanged MAC algorithms are ignored and there doesn't have to be
+%%% a matching MAC.
+
+aead_gcm_simultan('[email protected]', _) -> {'AEAD_AES_128_GCM', 'AEAD_AES_128_GCM'};
+aead_gcm_simultan('[email protected]', _) -> {'AEAD_AES_256_GCM', 'AEAD_AES_256_GCM'};
+aead_gcm_simultan('AEAD_AES_128_GCM', _) -> {'AEAD_AES_128_GCM', 'AEAD_AES_128_GCM'};
+aead_gcm_simultan('AEAD_AES_256_GCM', _) -> {'AEAD_AES_256_GCM', 'AEAD_AES_256_GCM'};
+aead_gcm_simultan(_, 'AEAD_AES_128_GCM') -> {'AEAD_AES_128_GCM', 'AEAD_AES_128_GCM'};
+aead_gcm_simultan(_, 'AEAD_AES_256_GCM') -> {'AEAD_AES_256_GCM', 'AEAD_AES_256_GCM'};
+aead_gcm_simultan(Cipher, Mac) -> {Cipher,Mac}.
+
+
select_encrypt_decrypt(client, Client, Server) ->
Encrypt =
select(Client#ssh_msg_kexinit.encryption_algorithms_client_to_server,
@@ -877,18 +862,18 @@ select_compression_decompression(client, Client, Server) ->
Compression =
select(Client#ssh_msg_kexinit.compression_algorithms_client_to_server,
Server#ssh_msg_kexinit.compression_algorithms_client_to_server),
- Decomprssion =
+ Decompression =
select(Client#ssh_msg_kexinit.compression_algorithms_server_to_client,
Server#ssh_msg_kexinit.compression_algorithms_server_to_client),
- {Compression, Decomprssion};
+ {Compression, Decompression};
select_compression_decompression(server, Client, Server) ->
- Decomprssion =
+ Decompression =
select(Client#ssh_msg_kexinit.compression_algorithms_client_to_server,
Server#ssh_msg_kexinit.compression_algorithms_client_to_server),
Compression =
select(Client#ssh_msg_kexinit.compression_algorithms_server_to_client,
Server#ssh_msg_kexinit.compression_algorithms_server_to_client),
- {Compression, Decomprssion}.
+ {Compression, Decompression}.
install_alg(SSH) ->
SSH1 = alg_final(SSH),
@@ -965,14 +950,39 @@ pack(Data, Ssh=#ssh{}) ->
%%% Note: pack/3 is only to be called from tests that wants
%%% to deliberetly send packets with wrong PacketLength!
%%% Use pack/2 for all other purposes!
-pack(Data0, #ssh{encrypt_block_size = BlockSize,
- send_sequence = SeqNum, send_mac = MacAlg,
- send_mac_key = MacKey,
- random_length_padding = RandomLengthPadding}
- = Ssh0,
- PacketLenDeviationForTests) when is_binary(Data0) ->
- {Ssh1, Data} = compress(Ssh0, Data0),
- PL = (BlockSize - ((4 + 1 + size(Data)) rem BlockSize)) rem BlockSize,
+pack(PlainText,
+ #ssh{send_sequence = SeqNum,
+ send_mac = MacAlg,
+ send_mac_key = MacKey,
+ encrypt = CryptoAlg} = Ssh0, PacketLenDeviationForTests) when is_binary(PlainText) ->
+
+ {Ssh1, CompressedPlainText} = compress(Ssh0, PlainText),
+ {EcryptedPacket, MAC, Ssh3} =
+ case pkt_type(CryptoAlg) of
+ common ->
+ PaddingLen = padding_length(4+1+size(CompressedPlainText), Ssh0),
+ Padding = ssh_bits:random(PaddingLen),
+ PlainPacketLen = 1 + PaddingLen + size(CompressedPlainText) + PacketLenDeviationForTests,
+ PlainPacketData = <<?UINT32(PlainPacketLen),?BYTE(PaddingLen), CompressedPlainText/binary, Padding/binary>>,
+ {Ssh2, EcryptedPacket0} = encrypt(Ssh1, PlainPacketData),
+ MAC0 = mac(MacAlg, MacKey, SeqNum, PlainPacketData),
+ {EcryptedPacket0, MAC0, Ssh2};
+ aead ->
+ PaddingLen = padding_length(1+size(CompressedPlainText), Ssh0),
+ Padding = ssh_bits:random(PaddingLen),
+ PlainPacketLen = 1 + PaddingLen + size(CompressedPlainText) + PacketLenDeviationForTests,
+ PlainPacketData = <<?BYTE(PaddingLen), CompressedPlainText/binary, Padding/binary>>,
+ {Ssh2, {EcryptedPacket0,MAC0}} = encrypt(Ssh1, {<<?UINT32(PlainPacketLen)>>,PlainPacketData}),
+ {<<?UINT32(PlainPacketLen),EcryptedPacket0/binary>>, MAC0, Ssh2}
+ end,
+ FinalPacket = [EcryptedPacket, MAC],
+ Ssh = Ssh3#ssh{send_sequence = (SeqNum+1) band 16#ffffffff},
+ {FinalPacket, Ssh}.
+
+
+padding_length(Size, #ssh{encrypt_block_size = BlockSize,
+ random_length_padding = RandomLengthPadding}) ->
+ PL = (BlockSize - (Size rem BlockSize)) rem BlockSize,
MinPaddingLen = if PL < 4 -> PL + BlockSize;
true -> PL
end,
@@ -981,45 +991,91 @@ pack(Data0, #ssh{encrypt_block_size = BlockSize,
ExtraPaddingLen = try crypto:rand_uniform(0,MaxExtraBlocks)*PadBlockSize
catch _:_ -> 0
end,
- PaddingLen = MinPaddingLen + ExtraPaddingLen,
- Padding = ssh_bits:random(PaddingLen),
- PacketLen = 1 + PaddingLen + size(Data) + PacketLenDeviationForTests,
- PacketData = <<?UINT32(PacketLen),?BYTE(PaddingLen),
- Data/binary, Padding/binary>>,
- {Ssh2, EncPacket} = encrypt(Ssh1, PacketData),
- MAC = mac(MacAlg, MacKey, SeqNum, PacketData),
- Packet = [EncPacket, MAC],
- Ssh = Ssh2#ssh{send_sequence = (SeqNum+1) band 16#ffffffff},
- {Packet, Ssh}.
-
-unpack(EncodedSoFar, ReminingLenght, #ssh{recv_mac_size = MacSize} = Ssh0) ->
- SshLength = ReminingLenght - MacSize,
- {NoMac, Mac, Rest} = case MacSize of
- 0 ->
- <<NoMac0:SshLength/binary,
- Rest0/binary>> = EncodedSoFar,
- {NoMac0, <<>>, Rest0};
- _ ->
- <<NoMac0:SshLength/binary,
- Mac0:MacSize/binary,
- Rest0/binary>> = EncodedSoFar,
- {NoMac0, Mac0, Rest0}
- end,
- {Ssh1, DecData, <<>>} =
- case SshLength of
- 0 ->
- {Ssh0, <<>>, <<>>};
- _ ->
- decrypt_blocks(NoMac, SshLength, Ssh0)
- end,
- {Ssh1, DecData, Rest, Mac}.
+ MinPaddingLen + ExtraPaddingLen.
+
+
+
+handle_packet_part(<<>>, Encrypted0, undefined, #ssh{decrypt = CryptoAlg} = Ssh0) ->
+ %% New ssh packet
+ case get_length(pkt_type(CryptoAlg), Encrypted0, Ssh0) of
+ get_more ->
+ %% too short to get the length
+ {get_more, <<>>, Encrypted0, undefined, Ssh0};
+
+ {ok, PacketLen, _, _, _} when PacketLen > ?SSH_MAX_PACKET_SIZE ->
+ %% far too long message than expected
+ {error, {exceeds_max_size,PacketLen}};
+
+ {ok, PacketLen, Decrypted, Encrypted1,
+ #ssh{recv_mac_size = MacSize} = Ssh1} ->
+ %% enough bytes so we got the length and can calculate how many
+ %% more bytes to expect for a full packet
+ TotalNeeded = (4 + PacketLen + MacSize),
+ handle_packet_part(Decrypted, Encrypted1, TotalNeeded, Ssh1)
+ end;
-msg_data(PacketData) ->
- <<Len:32, PaddingLen:8, _/binary>> = PacketData,
- DataLen = Len - PaddingLen - 1,
- <<_:32, _:8, Data:DataLen/binary,
- _:PaddingLen/binary>> = PacketData,
- Data.
+handle_packet_part(DecryptedPfx, EncryptedBuffer, TotalNeeded, Ssh0)
+ when (size(DecryptedPfx)+size(EncryptedBuffer)) < TotalNeeded ->
+ %% need more bytes to finalize the packet
+ {get_more, DecryptedPfx, EncryptedBuffer, TotalNeeded, Ssh0};
+
+handle_packet_part(DecryptedPfx, EncryptedBuffer, TotalNeeded,
+ #ssh{recv_mac_size = MacSize,
+ decrypt = CryptoAlg} = Ssh0) ->
+ %% enough bytes to decode the packet.
+ DecryptLen = TotalNeeded - size(DecryptedPfx) - MacSize,
+ <<EncryptedSfx:DecryptLen/binary, Mac:MacSize/binary, NextPacketBytes/binary>> = EncryptedBuffer,
+ case pkt_type(CryptoAlg) of
+ common ->
+ {Ssh1, DecryptedSfx} = decrypt(Ssh0, EncryptedSfx),
+ DecryptedPacket = <<DecryptedPfx/binary, DecryptedSfx/binary>>,
+ case is_valid_mac(Mac, DecryptedPacket, Ssh1) of
+ false ->
+ {bad_mac, Ssh1};
+ true ->
+ {Ssh, DecompressedPayload} = decompress(Ssh1, payload(DecryptedPacket)),
+ {decoded, DecompressedPayload, NextPacketBytes, Ssh}
+ end;
+ aead ->
+ PacketLenBin = DecryptedPfx,
+ case decrypt(Ssh0, {PacketLenBin,EncryptedSfx,Mac}) of
+ {Ssh1, error} ->
+ {bad_mac, Ssh1};
+ {Ssh1, DecryptedSfx} ->
+ DecryptedPacket = <<DecryptedPfx/binary, DecryptedSfx/binary>>,
+ {Ssh, DecompressedPayload} = decompress(Ssh1, payload(DecryptedPacket)),
+ {decoded, DecompressedPayload, NextPacketBytes, Ssh}
+ end
+ end.
+
+
+get_length(common, EncryptedBuffer, #ssh{decrypt_block_size = BlockSize} = Ssh0) ->
+ case size(EncryptedBuffer) >= erlang:max(8, BlockSize) of
+ true ->
+ <<EncBlock:BlockSize/binary, EncryptedRest/binary>> = EncryptedBuffer,
+ {Ssh,
+ <<?UINT32(PacketLen),_/binary>> = Decrypted} = decrypt(Ssh0, EncBlock),
+ {ok, PacketLen, Decrypted, EncryptedRest, Ssh};
+ false ->
+ get_more
+ end;
+get_length(aead, EncryptedBuffer, Ssh) ->
+ case size(EncryptedBuffer) >= 4 of
+ true ->
+ <<?UINT32(PacketLen), EncryptedRest/binary>> = EncryptedBuffer,
+ {ok, PacketLen, <<?UINT32(PacketLen)>>, EncryptedRest, Ssh};
+ false ->
+ get_more
+ end.
+
+pkt_type('AEAD_AES_128_GCM') -> aead;
+pkt_type('AEAD_AES_256_GCM') -> aead;
+pkt_type(_) -> common.
+
+payload(<<PacketLen:32, PaddingLen:8, PayloadAndPadding/binary>>) ->
+ PayloadLen = PacketLen - PaddingLen - 1,
+ <<Payload:PayloadLen/binary, _/binary>> = PayloadAndPadding,
+ Payload.
sign(SigData, Hash, #'DSAPrivateKey'{} = Key) ->
DerSignature = public_key:sign(SigData, Hash, Key),
@@ -1045,6 +1101,7 @@ verify(PlainText, Hash, Sig, {#'ECPoint'{},_} = Key) ->
verify(PlainText, Hash, Sig, Key) ->
public_key:verify(PlainText, Hash, Sig, Key).
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% Encryption
@@ -1053,6 +1110,30 @@ verify(PlainText, Hash, Sig, Key) ->
encrypt_init(#ssh{encrypt = none} = Ssh) ->
{ok, Ssh};
+encrypt_init(#ssh{encrypt = 'AEAD_AES_128_GCM', role = client} = Ssh) ->
+ IV = hash(Ssh, "A", 12*8),
+ <<K:16/binary>> = hash(Ssh, "C", 128),
+ {ok, Ssh#ssh{encrypt_keys = K,
+ encrypt_block_size = 16,
+ encrypt_ctx = IV}};
+encrypt_init(#ssh{encrypt = 'AEAD_AES_128_GCM', role = server} = Ssh) ->
+ IV = hash(Ssh, "B", 12*8),
+ <<K:16/binary>> = hash(Ssh, "D", 128),
+ {ok, Ssh#ssh{encrypt_keys = K,
+ encrypt_block_size = 16,
+ encrypt_ctx = IV}};
+encrypt_init(#ssh{encrypt = 'AEAD_AES_256_GCM', role = client} = Ssh) ->
+ IV = hash(Ssh, "A", 12*8),
+ <<K:32/binary>> = hash(Ssh, "C", 256),
+ {ok, Ssh#ssh{encrypt_keys = K,
+ encrypt_block_size = 16,
+ encrypt_ctx = IV}};
+encrypt_init(#ssh{encrypt = 'AEAD_AES_256_GCM', role = server} = Ssh) ->
+ IV = hash(Ssh, "B", 12*8),
+ <<K:32/binary>> = hash(Ssh, "D", 256),
+ {ok, Ssh#ssh{encrypt_keys = K,
+ encrypt_block_size = 16,
+ encrypt_ctx = IV}};
encrypt_init(#ssh{encrypt = '3des-cbc', role = client} = Ssh) ->
IV = hash(Ssh, "A", 64),
<<K1:8/binary, K2:8/binary, K3:8/binary>> = hash(Ssh, "C", 192),
@@ -1129,6 +1210,18 @@ encrypt_final(Ssh) ->
encrypt(#ssh{encrypt = none} = Ssh, Data) ->
{Ssh, Data};
+encrypt(#ssh{encrypt = 'AEAD_AES_128_GCM',
+ encrypt_keys = K,
+ encrypt_ctx = IV0} = Ssh, Data={_AAD,_Ptext}) ->
+ Enc = {_Ctext,_Ctag} = crypto:block_encrypt(aes_gcm, K, IV0, Data),
+ IV = next_gcm_iv(IV0),
+ {Ssh#ssh{encrypt_ctx = IV}, Enc};
+encrypt(#ssh{encrypt = 'AEAD_AES_256_GCM',
+ encrypt_keys = K,
+ encrypt_ctx = IV0} = Ssh, Data={_AAD,_Ptext}) ->
+ Enc = {_Ctext,_Ctag} = crypto:block_encrypt(aes_gcm, K, IV0, Data),
+ IV = next_gcm_iv(IV0),
+ {Ssh#ssh{encrypt_ctx = IV}, Enc};
encrypt(#ssh{encrypt = '3des-cbc',
encrypt_keys = {K1,K2,K3},
encrypt_ctx = IV0} = Ssh, Data) ->
@@ -1161,6 +1254,30 @@ encrypt(#ssh{encrypt = 'aes256-ctr',
decrypt_init(#ssh{decrypt = none} = Ssh) ->
{ok, Ssh};
+decrypt_init(#ssh{decrypt = 'AEAD_AES_128_GCM', role = client} = Ssh) ->
+ IV = hash(Ssh, "B", 12*8),
+ <<K:16/binary>> = hash(Ssh, "D", 128),
+ {ok, Ssh#ssh{decrypt_keys = K,
+ decrypt_block_size = 16,
+ decrypt_ctx = IV}};
+decrypt_init(#ssh{decrypt = 'AEAD_AES_128_GCM', role = server} = Ssh) ->
+ IV = hash(Ssh, "A", 12*8),
+ <<K:16/binary>> = hash(Ssh, "C", 128),
+ {ok, Ssh#ssh{decrypt_keys = K,
+ decrypt_block_size = 16,
+ decrypt_ctx = IV}};
+decrypt_init(#ssh{decrypt = 'AEAD_AES_256_GCM', role = client} = Ssh) ->
+ IV = hash(Ssh, "B", 12*8),
+ <<K:32/binary>> = hash(Ssh, "D", 256),
+ {ok, Ssh#ssh{decrypt_keys = K,
+ decrypt_block_size = 16,
+ decrypt_ctx = IV}};
+decrypt_init(#ssh{decrypt = 'AEAD_AES_256_GCM', role = server} = Ssh) ->
+ IV = hash(Ssh, "A", 12*8),
+ <<K:32/binary>> = hash(Ssh, "C", 256),
+ {ok, Ssh#ssh{decrypt_keys = K,
+ decrypt_block_size = 16,
+ decrypt_ctx = IV}};
decrypt_init(#ssh{decrypt = '3des-cbc', role = client} = Ssh) ->
{IV, KD} = {hash(Ssh, "B", 64),
hash(Ssh, "D", 192)},
@@ -1235,8 +1352,22 @@ decrypt_final(Ssh) ->
decrypt_ctx = undefined,
decrypt_block_size = 8}}.
+decrypt(Ssh, <<>>) ->
+ {Ssh, <<>>};
decrypt(#ssh{decrypt = none} = Ssh, Data) ->
{Ssh, Data};
+decrypt(#ssh{decrypt = 'AEAD_AES_128_GCM',
+ decrypt_keys = K,
+ decrypt_ctx = IV0} = Ssh, Data = {_AAD,_Ctext,_Ctag}) ->
+ Dec = crypto:block_decrypt(aes_gcm, K, IV0, Data), % Dec = PlainText | error
+ IV = next_gcm_iv(IV0),
+ {Ssh#ssh{decrypt_ctx = IV}, Dec};
+decrypt(#ssh{decrypt = 'AEAD_AES_256_GCM',
+ decrypt_keys = K,
+ decrypt_ctx = IV0} = Ssh, Data = {_AAD,_Ctext,_Ctag}) ->
+ Dec = crypto:block_decrypt(aes_gcm, K, IV0, Data), % Dec = PlainText | error
+ IV = next_gcm_iv(IV0),
+ {Ssh#ssh{decrypt_ctx = IV}, Dec};
decrypt(#ssh{decrypt = '3des-cbc', decrypt_keys = Keys,
decrypt_ctx = IV0} = Ssh, Data) ->
{K1, K2, K3} = Keys,
@@ -1261,6 +1392,10 @@ decrypt(#ssh{decrypt = 'aes256-ctr',
{State, Enc} = crypto:stream_decrypt(State0,Data),
{Ssh#ssh{decrypt_ctx = State}, Enc}.
+
+next_gcm_iv(<<Fixed:32, InvCtr:64>>) -> <<Fixed:32, (InvCtr+1):64>>.
+
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Compression
%%
@@ -1349,28 +1484,42 @@ decompress(#ssh{decompress = '[email protected]', decompress_ctx = Context, authe
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
send_mac_init(SSH) ->
- case SSH#ssh.role of
- client ->
- KeySize =mac_key_size(SSH#ssh.send_mac),
- Key = hash(SSH, "E", KeySize),
- {ok, SSH#ssh { send_mac_key = Key }};
- server ->
- KeySize = mac_key_size(SSH#ssh.send_mac),
- Key = hash(SSH, "F", KeySize),
- {ok, SSH#ssh { send_mac_key = Key }}
+ case pkt_type(SSH#ssh.send_mac) of
+ common ->
+ case SSH#ssh.role of
+ client ->
+ KeySize = mac_key_size(SSH#ssh.send_mac),
+ Key = hash(SSH, "E", KeySize),
+ {ok, SSH#ssh { send_mac_key = Key }};
+ server ->
+ KeySize = mac_key_size(SSH#ssh.send_mac),
+ Key = hash(SSH, "F", KeySize),
+ {ok, SSH#ssh { send_mac_key = Key }}
+ end;
+ aead ->
+ %% Not applicable
+ {ok, SSH}
end.
send_mac_final(SSH) ->
- {ok, SSH#ssh { send_mac = none, send_mac_key = undefined }}.
+ {ok, SSH#ssh {send_mac = none,
+ send_mac_key = undefined }}.
+
recv_mac_init(SSH) ->
- case SSH#ssh.role of
- client ->
- Key = hash(SSH, "F", mac_key_size(SSH#ssh.recv_mac)),
- {ok, SSH#ssh { recv_mac_key = Key }};
- server ->
- Key = hash(SSH, "E", mac_key_size(SSH#ssh.recv_mac)),
- {ok, SSH#ssh { recv_mac_key = Key }}
+ case pkt_type(SSH#ssh.recv_mac) of
+ common ->
+ case SSH#ssh.role of
+ client ->
+ Key = hash(SSH, "F", mac_key_size(SSH#ssh.recv_mac)),
+ {ok, SSH#ssh { recv_mac_key = Key }};
+ server ->
+ Key = hash(SSH, "E", mac_key_size(SSH#ssh.recv_mac)),
+ {ok, SSH#ssh { recv_mac_key = Key }}
+ end;
+ aead ->
+ %% Not applicable
+ {ok, SSH}
end.
recv_mac_final(SSH) ->
@@ -1453,8 +1602,11 @@ kex_h(SSH, Curve, Key, Q_c, Q_s, K) ->
crypto:hash(sha(Curve), L).
kex_h(SSH, Key, Min, NBits, Max, Prime, Gen, E, F, K) ->
+ KeyBin = public_key:ssh_encode(Key, ssh2_pubkey),
L = if Min==-1; Max==-1 ->
- KeyBin = public_key:ssh_encode(Key, ssh2_pubkey),
+ %% flag from 'ssh_msg_kex_dh_gex_request_old'
+ %% It was like this before that message was supported,
+ %% why?
Ts = [string,string,binary,binary,binary,
uint32,
mpint,mpint,mpint,mpint,mpint],
@@ -1463,7 +1615,6 @@ kex_h(SSH, Key, Min, NBits, Max, Prime, Gen, E, F, K) ->
KeyBin, NBits, Prime, Gen, E,F,K],
Ts);
true ->
- KeyBin = public_key:ssh_encode(Key, ssh2_pubkey),
Ts = [string,string,binary,binary,binary,
uint32,uint32,uint32,
mpint,mpint,mpint,mpint,mpint],
@@ -1501,6 +1652,8 @@ mac_digest_size('hmac-md5') -> 20;
mac_digest_size('hmac-md5-96') -> 12;
mac_digest_size('hmac-sha2-256') -> 32;
mac_digest_size('hmac-sha2-512') -> 64;
+mac_digest_size('AEAD_AES_128_GCM') -> 16;
+mac_digest_size('AEAD_AES_256_GCM') -> 16;
mac_digest_size(none) -> 0.
peer_name({Host, _}) ->
@@ -1530,6 +1683,68 @@ ecdh_curve('ecdh-sha2-nistp256') -> secp256r1;
ecdh_curve('ecdh-sha2-nistp384') -> secp384r1;
ecdh_curve('ecdh-sha2-nistp521') -> secp521r1.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Utils for default_algorithms/1 and supported_algorithms/1
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+supported_algorithms(Key, [{client2server,BL1},{server2client,BL2}]) ->
+ [{client2server,As1},{server2client,As2}] = supported_algorithms(Key),
+ [{client2server,As1--BL1},{server2client,As2--BL2}];
+supported_algorithms(Key, BlackList) ->
+ supported_algorithms(Key) -- BlackList.
+
+
+select_crypto_supported(L) ->
+ Sup = [{ec_curve,crypto_supported_curves()} | crypto:supports()],
+ [Name || {Name,CryptoRequires} <- L,
+ crypto_supported(CryptoRequires, Sup)].
+
+crypto_supported_curves() ->
+ try crypto:ec_curves()
+ catch _:_ -> []
+ end.
+
+crypto_supported(Conditions, Supported) ->
+ lists:all( fun({Tag,CryptoName}) when is_atom(CryptoName) ->
+ crypto_name_supported(Tag,CryptoName,Supported);
+ ({Tag,{Name,Len}}) when is_integer(Len) ->
+ crypto_name_supported(Tag,Name,Supported) andalso
+ len_supported(Name,Len)
+ end, Conditions).
+
+crypto_name_supported(Tag, CryptoName, Supported) ->
+ lists:member(CryptoName, proplists:get_value(Tag,Supported,[])).
+
+len_supported(Name, Len) ->
+ try
+ case Name of
+ aes_ctr ->
+ {_, <<_/binary>>} =
+ %% Test encryption
+ crypto:stream_encrypt(crypto:stream_init(Name, <<0:Len>>, <<0:128>>), <<"">>);
+ aes_gcm ->
+ {<<_/binary>>, <<_/binary>>} =
+ crypto:block_encrypt(Name,
+ _Key = <<0:Len>>,
+ _IV = <<0:12/unsigned-unit:8>>,
+ {<<"AAD">>,"PT"})
+ end
+ of
+ _ -> true
+ catch
+ _:_ -> false
+ end.
+
+
+same(Algs) -> [{client2server,Algs}, {server2client,Algs}].
+
+
+%% default_algorithms(kex) -> % Example of how to disable an algorithm
+%% supported_algorithms(kex, ['ecdh-sha2-nistp521']);
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% Other utils
diff --git a/lib/ssh/test/Makefile b/lib/ssh/test/Makefile
index 96c74c6c8a..781a876723 100644
--- a/lib/ssh/test/Makefile
+++ b/lib/ssh/test/Makefile
@@ -47,6 +47,8 @@ MODULES= \
ssh_to_openssh_SUITE \
ssh_upgrade_SUITE \
ssh_test_lib \
+ ssh_key_cb \
+ ssh_key_cb_options \
ssh_trpt_test_lib \
ssh_echo_server \
ssh_peername_sockname_server \
diff --git a/lib/ssh/test/ssh_algorithms_SUITE.erl b/lib/ssh/test/ssh_algorithms_SUITE.erl
index 85415a17de..f0ac92fef6 100644
--- a/lib/ssh/test/ssh_algorithms_SUITE.erl
+++ b/lib/ssh/test/ssh_algorithms_SUITE.erl
@@ -69,6 +69,9 @@ two_way_tags() -> [cipher,mac,compression].
%%--------------------------------------------------------------------
init_per_suite(Config) ->
+ ct:log("os:getenv(\"HOME\") = ~p~n"
+ "init:get_argument(home) = ~p",
+ [os:getenv("HOME"), init:get_argument(home)]),
ct:log("~n~n"
"OS ssh:~n=======~n~p~n~n~n"
"Erl ssh:~n========~n~p~n~n~n"
@@ -358,7 +361,9 @@ start_pubkey_daemon(Opts, Config) ->
setup_pubkey(Config) ->
DataDir = ?config(data_dir, Config),
UserDir = ?config(priv_dir, Config),
- ssh_test_lib:setup_dsa_known_host(DataDir, UserDir),
+ ssh_test_lib:setup_dsa(DataDir, UserDir),
+ ssh_test_lib:setup_rsa(DataDir, UserDir),
+ ssh_test_lib:setup_ecdsa("256", DataDir, UserDir),
Config.
diff --git a/lib/ssh/test/ssh_algorithms_SUITE_data/id_ecdsa b/lib/ssh/test/ssh_algorithms_SUITE_data/id_ecdsa
new file mode 100644
index 0000000000..4b1eb12eaa
--- /dev/null
+++ b/lib/ssh/test/ssh_algorithms_SUITE_data/id_ecdsa
@@ -0,0 +1,5 @@
+-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEIJfCaBKIIKhjbJl5F8BedqlXOQYDX5ba9Skypllmx/w+oAoGCCqGSM49
+AwEHoUQDQgAE49RbK2xQ/19ji3uDPM7uT4692LbwWF1TiaA9vUuebMGazoW/98br
+N9xZu0L1AWwtEjs3kmJDTB7eJEGXnjUAcQ==
+-----END EC PRIVATE KEY-----
diff --git a/lib/ssh/test/ssh_algorithms_SUITE_data/id_ecdsa.pub b/lib/ssh/test/ssh_algorithms_SUITE_data/id_ecdsa.pub
new file mode 100644
index 0000000000..a0147e60fa
--- /dev/null
+++ b/lib/ssh/test/ssh_algorithms_SUITE_data/id_ecdsa.pub
@@ -0,0 +1 @@
+ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBOPUWytsUP9fY4t7gzzO7k+Ovdi28FhdU4mgPb1LnmzBms6Fv/fG6zfcWbtC9QFsLRI7N5JiQ0we3iRBl541AHE= uabhnil@elxadlj3q32
diff --git a/lib/ssh/test/ssh_algorithms_SUITE_data/id_ecdsa256 b/lib/ssh/test/ssh_algorithms_SUITE_data/id_ecdsa256
new file mode 100644
index 0000000000..4b1eb12eaa
--- /dev/null
+++ b/lib/ssh/test/ssh_algorithms_SUITE_data/id_ecdsa256
@@ -0,0 +1,5 @@
+-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEIJfCaBKIIKhjbJl5F8BedqlXOQYDX5ba9Skypllmx/w+oAoGCCqGSM49
+AwEHoUQDQgAE49RbK2xQ/19ji3uDPM7uT4692LbwWF1TiaA9vUuebMGazoW/98br
+N9xZu0L1AWwtEjs3kmJDTB7eJEGXnjUAcQ==
+-----END EC PRIVATE KEY-----
diff --git a/lib/ssh/test/ssh_algorithms_SUITE_data/id_ecdsa256.pub b/lib/ssh/test/ssh_algorithms_SUITE_data/id_ecdsa256.pub
new file mode 100644
index 0000000000..a0147e60fa
--- /dev/null
+++ b/lib/ssh/test/ssh_algorithms_SUITE_data/id_ecdsa256.pub
@@ -0,0 +1 @@
+ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBOPUWytsUP9fY4t7gzzO7k+Ovdi28FhdU4mgPb1LnmzBms6Fv/fG6zfcWbtC9QFsLRI7N5JiQ0we3iRBl541AHE= uabhnil@elxadlj3q32
diff --git a/lib/ssh/test/ssh_algorithms_SUITE_data/ssh_host_ecdsa_key256 b/lib/ssh/test/ssh_algorithms_SUITE_data/ssh_host_ecdsa_key256
new file mode 100644
index 0000000000..2979ea88ed
--- /dev/null
+++ b/lib/ssh/test/ssh_algorithms_SUITE_data/ssh_host_ecdsa_key256
@@ -0,0 +1,5 @@
+-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEIMe4MDoit0t8RzSVPwkCBemQ9fhXL+xnTSAWISw8HNCioAoGCCqGSM49
+AwEHoUQDQgAEo2q7U3P6r0W5WGOLtM78UQtofM9UalEhiZeDdiyylsR/RR17Op0s
+VPGSADLmzzgcucLEKy17j2S+oz42VUJy5A==
+-----END EC PRIVATE KEY-----
diff --git a/lib/ssh/test/ssh_algorithms_SUITE_data/ssh_host_ecdsa_key256.pub b/lib/ssh/test/ssh_algorithms_SUITE_data/ssh_host_ecdsa_key256.pub
new file mode 100644
index 0000000000..85dc419345
--- /dev/null
+++ b/lib/ssh/test/ssh_algorithms_SUITE_data/ssh_host_ecdsa_key256.pub
@@ -0,0 +1 @@
+ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBKNqu1Nz+q9FuVhji7TO/FELaHzPVGpRIYmXg3YsspbEf0UdezqdLFTxkgAy5s84HLnCxCste49kvqM+NlVCcuQ= uabhnil@elxadlj3q32
diff --git a/lib/ssh/test/ssh_basic_SUITE.erl b/lib/ssh/test/ssh_basic_SUITE.erl
index 400edb4d2c..6c4c215b3d 100644
--- a/lib/ssh/test/ssh_basic_SUITE.erl
+++ b/lib/ssh/test/ssh_basic_SUITE.erl
@@ -36,9 +36,15 @@
cli/1,
close/1,
daemon_already_started/1,
+ daemon_opt_fd/1,
+ multi_daemon_opt_fd/1,
double_close/1,
exec/1,
exec_compressed/1,
+ exec_key_differs1/1,
+ exec_key_differs2/1,
+ exec_key_differs3/1,
+ exec_key_differs_fail/1,
idle_time/1,
inet6_option/1,
inet_option/1,
@@ -52,8 +58,10 @@
send/1,
shell/1,
shell_no_unicode/1,
- shell_unicode_string/1,
- ssh_info_print/1
+ shell_unicode_string/1,
+ ssh_info_print/1,
+ key_callback/1,
+ key_callback_options/1
]).
%%% Common test callbacks
@@ -82,9 +90,13 @@ all() ->
{group, ecdsa_sha2_nistp521_key},
{group, dsa_pass_key},
{group, rsa_pass_key},
+ {group, host_user_key_differs},
+ {group, key_cb},
{group, internal_error},
daemon_already_started,
double_close,
+ daemon_opt_fd,
+ multi_daemon_opt_fd,
packet_size_zero,
ssh_info_print
].
@@ -95,8 +107,13 @@ groups() ->
{ecdsa_sha2_nistp256_key, [], basic_tests()},
{ecdsa_sha2_nistp384_key, [], basic_tests()},
{ecdsa_sha2_nistp521_key, [], basic_tests()},
+ {host_user_key_differs, [], [exec_key_differs1,
+ exec_key_differs2,
+ exec_key_differs3,
+ exec_key_differs_fail]},
{dsa_pass_key, [], [pass_phrase]},
{rsa_pass_key, [], [pass_phrase]},
+ {key_cb, [], [key_callback, key_callback_options]},
{internal_error, [], [internal_error]}
].
@@ -176,6 +193,26 @@ init_per_group(dsa_pass_key, Config) ->
PrivDir = ?config(priv_dir, Config),
ssh_test_lib:setup_dsa_pass_pharse(DataDir, PrivDir, "Password"),
[{pass_phrase, {dsa_pass_phrase, "Password"}}| Config];
+init_per_group(host_user_key_differs, Config) ->
+ Data = ?config(data_dir, Config),
+ Sys = filename:join(?config(priv_dir, Config), system_rsa),
+ SysUsr = filename:join(Sys, user),
+ Usr = filename:join(?config(priv_dir, Config), user_ecdsa_256),
+ file:make_dir(Sys),
+ file:make_dir(SysUsr),
+ file:make_dir(Usr),
+ file:copy(filename:join(Data, "ssh_host_rsa_key"), filename:join(Sys, "ssh_host_rsa_key")),
+ file:copy(filename:join(Data, "ssh_host_rsa_key.pub"), filename:join(Sys, "ssh_host_rsa_key.pub")),
+ file:copy(filename:join(Data, "id_ecdsa256"), filename:join(Usr, "id_ecdsa")),
+ file:copy(filename:join(Data, "id_ecdsa256.pub"), filename:join(Usr, "id_ecdsa.pub")),
+ ssh_test_lib:setup_ecdsa_auth_keys("256", Usr, SysUsr),
+ ssh_test_lib:setup_rsa_known_host(Sys, Usr),
+ Config;
+init_per_group(key_cb, Config) ->
+ DataDir = ?config(data_dir, Config),
+ PrivDir = ?config(priv_dir, Config),
+ ssh_test_lib:setup_dsa(DataDir, PrivDir),
+ Config;
init_per_group(internal_error, Config) ->
DataDir = ?config(data_dir, Config),
PrivDir = ?config(priv_dir, Config),
@@ -243,6 +280,10 @@ end_per_group(rsa_pass_key, Config) ->
PrivDir = ?config(priv_dir, Config),
ssh_test_lib:clean_rsa(PrivDir),
Config;
+end_per_group(key_cb, Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ ssh_test_lib:clean_dsa(PrivDir),
+ Config;
end_per_group(internal_error, Config) ->
PrivDir = ?config(priv_dir, Config),
ssh_test_lib:clean_dsa(PrivDir),
@@ -270,6 +311,14 @@ init_per_testcase(TC, Config) when TC==shell_no_unicode ;
ct:log("file:native_name_encoding() = ~p,~nio:getopts() = ~p",
[file:native_name_encoding(),io:getopts()]),
wait_for_erlang_first_line([{io,IO}, {shell,Shell}, {sftpd, Sftpd} | Config]);
+
+init_per_testcase(inet6_option, Config) ->
+ case ssh_test_lib:has_inet6_address() of
+ true ->
+ init_per_testcase('__default__', Config);
+ false ->
+ {skip,"No ipv6 interface address"}
+ end;
init_per_testcase(_TestCase, Config) ->
ssh:start(),
Config.
@@ -474,6 +523,80 @@ shell(Config) when is_list(Config) ->
end.
%%--------------------------------------------------------------------
+%%% Test that we could user different types of host pubkey and user pubkey
+exec_key_differs1(Config) -> exec_key_differs(Config, ['ecdsa-sha2-nistp256']).
+
+exec_key_differs2(Config) -> exec_key_differs(Config, ['ssh-dss','ecdsa-sha2-nistp256']).
+
+exec_key_differs3(Config) -> exec_key_differs(Config, ['ecdsa-sha2-nistp384','ecdsa-sha2-nistp256']).
+
+
+
+exec_key_differs(Config, UserPKAlgs) ->
+ case lists:usort(['ssh-rsa'|UserPKAlgs])
+ -- ssh_transport:supported_algorithms(public_key)
+ of
+ [] ->
+ process_flag(trap_exit, true),
+ SystemDir = filename:join(?config(priv_dir, Config), system_rsa),
+ SystemUserDir = filename:join(SystemDir, user),
+ UserDir = filename:join(?config(priv_dir, Config), user_ecdsa_256),
+
+ {_Pid, _Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},
+ {user_dir, SystemUserDir},
+ {preferred_algorithms,
+ [{public_key,['ssh-rsa']}]}]),
+ ct:sleep(500),
+
+ IO = ssh_test_lib:start_io_server(),
+ Shell = ssh_test_lib:start_shell(Port, IO, UserDir,
+ [{preferred_algorithms,[{public_key,['ssh-rsa']}]},
+ {pref_public_key_algs,UserPKAlgs}
+ ]),
+
+
+ receive
+ {'EXIT', _, _} ->
+ ct:fail(no_ssh_connection);
+ ErlShellStart ->
+ ct:log("Erlang shell start: ~p~n", [ErlShellStart]),
+ do_shell(IO, Shell)
+ after
+ 30000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE])
+ end;
+
+ UnsupportedPubKeys ->
+ {skip, io_lib:format("~p unsupported",[UnsupportedPubKeys])}
+ end.
+
+%%--------------------------------------------------------------------
+exec_key_differs_fail(Config) when is_list(Config) ->
+ process_flag(trap_exit, true),
+ SystemDir = filename:join(?config(priv_dir, Config), system_rsa),
+ SystemUserDir = filename:join(SystemDir, user),
+ UserDir = filename:join(?config(priv_dir, Config), user_ecdsa_256),
+
+ {_Pid, _Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},
+ {user_dir, SystemUserDir},
+ {preferred_algorithms,
+ [{public_key,['ssh-rsa']}]}]),
+ ct:sleep(500),
+
+ IO = ssh_test_lib:start_io_server(),
+ ssh_test_lib:start_shell(Port, IO, UserDir,
+ [{preferred_algorithms,[{public_key,['ssh-rsa']}]},
+ {pref_public_key_algs,['ssh-dss']}]),
+ receive
+ {'EXIT', _, _} ->
+ ok;
+ ErlShellStart ->
+ ct:log("Erlang shell start: ~p~n", [ErlShellStart]),
+ ct:fail(connection_not_rejected)
+ after
+ 30000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE])
+ end.
+
+%%--------------------------------------------------------------------
cli(Config) when is_list(Config) ->
process_flag(trap_exit, true),
SystemDir = filename:join(?config(priv_dir, Config), system),
@@ -571,6 +694,56 @@ pass_phrase(Config) when is_list(Config) ->
{ok, _ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity),
ssh:stop_daemon(Pid).
+%%--------------------------------------------------------------------
+%%% Test that we can use key callback
+key_callback(Config) when is_list(Config) ->
+ process_flag(trap_exit, true),
+ SystemDir = filename:join(?config(priv_dir, Config), system),
+ UserDir = ?config(priv_dir, Config),
+ NoPubKeyDir = filename:join(UserDir, "nopubkey"),
+ file:make_dir(NoPubKeyDir),
+
+ {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},
+ {user_dir, UserDir},
+ {failfun, fun ssh_test_lib:failfun/2}]),
+
+ ConnectOpts = [{silently_accept_hosts, true},
+ {user_dir, NoPubKeyDir},
+ {user_interaction, false},
+ {key_cb, ssh_key_cb}],
+
+ ConnectionRef = ssh_test_lib:connect(Host, Port, ConnectOpts),
+
+ {ok, _ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity),
+ ssh:stop_daemon(Pid).
+
+
+%%--------------------------------------------------------------------
+%%% Test that we can use key callback with callback options
+key_callback_options(Config) when is_list(Config) ->
+ process_flag(trap_exit, true),
+ SystemDir = filename:join(?config(priv_dir, Config), system),
+ UserDir = ?config(priv_dir, Config),
+
+ NoPubKeyDir = filename:join(UserDir, "nopubkey"),
+ file:make_dir(NoPubKeyDir),
+
+ {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},
+ {user_dir, UserDir},
+ {failfun, fun ssh_test_lib:failfun/2}]),
+
+ {ok, PrivKey} = file:read_file(filename:join(UserDir, "id_dsa")),
+
+ ConnectOpts = [{silently_accept_hosts, true},
+ {user_dir, NoPubKeyDir},
+ {user_interaction, false},
+ {key_cb, {ssh_key_cb_options, [{priv_key, PrivKey}]}}],
+
+ ConnectionRef = ssh_test_lib:connect(Host, Port, ConnectOpts),
+
+ {ok, _ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity),
+ ssh:stop_daemon(Pid).
+
%%--------------------------------------------------------------------
%%% Test that client does not hang if disconnects due to internal error
@@ -705,6 +878,68 @@ double_close(Config) when is_list(Config) ->
ok = ssh:close(CM).
%%--------------------------------------------------------------------
+daemon_opt_fd(Config) ->
+ SystemDir = ?config(data_dir, Config),
+ PrivDir = ?config(priv_dir, Config),
+ UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth
+ file:make_dir(UserDir),
+
+ {ok,S1} = gen_tcp:listen(0,[]),
+ {ok,Fd1} = prim_inet:getfd(S1),
+
+ {ok,Pid1} = ssh:daemon(0, [{system_dir, SystemDir},
+ {fd,Fd1},
+ {user_dir, UserDir},
+ {user_passwords, [{"vego", "morot"}]},
+ {failfun, fun ssh_test_lib:failfun/2}]),
+
+ {ok,{_Host1,Port1}} = inet:sockname(S1),
+ {ok, C1} = ssh:connect("localhost", Port1, [{silently_accept_hosts, true},
+ {user_dir, UserDir},
+ {user, "vego"},
+ {password, "morot"},
+ {user_interaction, false}]),
+ exit(C1, {shutdown, normal}),
+ ssh:stop_daemon(Pid1),
+ gen_tcp:close(S1).
+
+
+%%--------------------------------------------------------------------
+multi_daemon_opt_fd(Config) ->
+ SystemDir = ?config(data_dir, Config),
+ PrivDir = ?config(priv_dir, Config),
+ UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth
+ file:make_dir(UserDir),
+
+ Test =
+ fun() ->
+ {ok,S} = gen_tcp:listen(0,[]),
+ {ok,Fd} = prim_inet:getfd(S),
+
+ {ok,Pid} = ssh:daemon(0, [{system_dir, SystemDir},
+ {fd,Fd},
+ {user_dir, UserDir},
+ {user_passwords, [{"vego", "morot"}]},
+ {failfun, fun ssh_test_lib:failfun/2}]),
+
+ {ok,{_Host,Port}} = inet:sockname(S),
+ {ok, C} = ssh:connect("localhost", Port, [{silently_accept_hosts, true},
+ {user_dir, UserDir},
+ {user, "vego"},
+ {password, "morot"},
+ {user_interaction, false}]),
+ {S,Pid,C}
+ end,
+
+ Tests = [Test(),Test(),Test(),Test(),Test(),Test()],
+
+ [begin
+ gen_tcp:close(S),
+ ssh:stop_daemon(Pid),
+ exit(C, {shutdown, normal})
+ end || {S,Pid,C} <- Tests].
+
+%%--------------------------------------------------------------------
packet_size_zero(Config) ->
SystemDir = ?config(data_dir, Config),
PrivDir = ?config(priv_dir, Config),
diff --git a/lib/ssh/test/ssh_key_cb.erl b/lib/ssh/test/ssh_key_cb.erl
new file mode 100644
index 0000000000..388ec2ecc1
--- /dev/null
+++ b/lib/ssh/test/ssh_key_cb.erl
@@ -0,0 +1,45 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2015. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%%----------------------------------------------------------------------
+
+%% Note: This module is used by ssh_basic_SUITE
+
+-module(ssh_key_cb).
+-behaviour(ssh_client_key_api).
+-compile(export_all).
+
+add_host_key(_, _, _) ->
+ ok.
+
+is_host_key(_, _, _, _) ->
+ true.
+
+user_key('ssh-dss', Opts) ->
+ UserDir = proplists:get_value(user_dir, Opts),
+ KeyFile = filename:join(filename:dirname(UserDir), "id_dsa"),
+ {ok, KeyBin} = file:read_file(KeyFile),
+ [Entry] = public_key:pem_decode(KeyBin),
+ Key = public_key:pem_entry_decode(Entry),
+ {ok, Key};
+
+user_key(_Alg, _Opt) ->
+ {error, "Not Supported"}.
diff --git a/lib/ssh/test/ssh_key_cb_options.erl b/lib/ssh/test/ssh_key_cb_options.erl
new file mode 100644
index 0000000000..afccb34f0f
--- /dev/null
+++ b/lib/ssh/test/ssh_key_cb_options.erl
@@ -0,0 +1,44 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2015. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%%----------------------------------------------------------------------
+
+%% Note: This module is used by ssh_basic_SUITE
+
+-module(ssh_key_cb_options).
+-behaviour(ssh_client_key_api).
+-compile(export_all).
+
+add_host_key(_, _, _) ->
+ ok.
+
+is_host_key(_, _, _, _) ->
+ true.
+
+user_key('ssh-dss', Opts) ->
+ KeyCbOpts = proplists:get_value(key_cb_private, Opts),
+ KeyBin = proplists:get_value(priv_key, KeyCbOpts),
+ [Entry] = public_key:pem_decode(KeyBin),
+ Key = public_key:pem_entry_decode(Entry),
+ {ok, Key};
+
+user_key(_Alg, _Opt) ->
+ {error, "Not Supported"}.
diff --git a/lib/ssh/test/ssh_protocol_SUITE.erl b/lib/ssh/test/ssh_protocol_SUITE.erl
index 3a7f47c2dd..5af60adfae 100644
--- a/lib/ssh/test/ssh_protocol_SUITE.erl
+++ b/lib/ssh/test/ssh_protocol_SUITE.erl
@@ -69,7 +69,9 @@ groups() ->
gex_client_init_option_groups,
gex_server_gex_limit,
gex_client_init_option_groups_moduli_file,
- gex_client_init_option_groups_file
+ gex_client_init_option_groups_file,
+ gex_client_old_request_exact,
+ gex_client_old_request_noexact
]},
{service_requests, [], [bad_service_name,
bad_long_service_name,
@@ -94,7 +96,9 @@ init_per_testcase(no_common_alg_server_disconnects, Config) ->
init_per_testcase(TC, Config) when TC == gex_client_init_option_groups ;
TC == gex_client_init_option_groups_moduli_file ;
TC == gex_client_init_option_groups_file ;
- TC == gex_server_gex_limit ->
+ TC == gex_server_gex_limit ;
+ TC == gex_client_old_request_exact ;
+ TC == gex_client_old_request_noexact ->
Opts = case TC of
gex_client_init_option_groups ->
[{dh_gex_groups, [{2345, 3, 41}]}];
@@ -106,8 +110,10 @@ init_per_testcase(TC, Config) when TC == gex_client_init_option_groups ;
DataDir = ?config(data_dir, Config),
F = filename:join(DataDir, "dh_group_test.moduli"),
[{dh_gex_groups, {ssh_moduli_file,F}}];
- gex_server_gex_limit ->
- [{dh_gex_groups, [{ 500, 3, 18},
+ _ when TC == gex_server_gex_limit ;
+ TC == gex_client_old_request_exact ;
+ TC == gex_client_old_request_noexact ->
+ [{dh_gex_groups, [{ 500, 3, 17},
{1000, 7, 91},
{3000, 5, 61}]},
{dh_gex_limits,{500,1500}}
@@ -126,7 +132,9 @@ end_per_testcase(no_common_alg_server_disconnects, Config) ->
end_per_testcase(TC, Config) when TC == gex_client_init_option_groups ;
TC == gex_client_init_option_groups_moduli_file ;
TC == gex_client_init_option_groups_file ;
- TC == gex_server_gex_limit ->
+ TC == gex_server_gex_limit ;
+ TC == gex_client_old_request_exact ;
+ TC == gex_client_old_request_noexact ->
stop_std_daemon(Config);
end_per_testcase(_TestCase, Config) ->
check_std_daemon_works(Config, ?LINE).
@@ -271,7 +279,9 @@ no_common_alg_server_disconnects(Config) ->
{send, ssh_msg_kexinit}, % with server unsupported 'ssh-dss' !
{match,
{'or',[#ssh_msg_disconnect{code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED, _='_'},
- tcp_closed]},
+ tcp_closed,
+ {tcp_error,econnaborted}
+ ]},
receive_msg}
]
).
@@ -381,6 +391,29 @@ do_gex_client_init(Config, {Min,N,Max}, {G,P}) ->
]
).
+%%%--------------------------------------------------------------------
+gex_client_old_request_exact(Config) -> do_gex_client_init_old(Config, 500, {3,17}).
+gex_client_old_request_noexact(Config) -> do_gex_client_init_old(Config, 800, {7,91}).
+
+do_gex_client_init_old(Config, N, {G,P}) ->
+ {ok,_} =
+ ssh_trpt_test_lib:exec(
+ [{set_options, [print_ops, print_seqnums, print_messages]},
+ {connect,
+ server_host(Config),server_port(Config),
+ [{silently_accept_hosts, true},
+ {user_dir, user_dir(Config)},
+ {user_interaction, false},
+ {preferred_algorithms,[{kex,['diffie-hellman-group-exchange-sha1']}]}
+ ]},
+ receive_hello,
+ {send, hello},
+ {send, ssh_msg_kexinit},
+ {match, #ssh_msg_kexinit{_='_'}, receive_msg},
+ {send, #ssh_msg_kex_dh_gex_request_old{n = N}},
+ {match, #ssh_msg_kex_dh_gex_group{p=P, g=G, _='_'}, receive_msg}
+ ]
+ ).
%%%--------------------------------------------------------------------
bad_service_name(Config) ->
@@ -444,7 +477,8 @@ bad_packet_length(Config, LengthExcess) ->
%% Prohibit remote decoder starvation:
{send, #ssh_msg_service_request{name="ssh-userauth"}},
{match, {'or',[#ssh_msg_disconnect{_='_'},
- tcp_closed
+ tcp_closed,
+ {tcp_error,econnaborted}
]},
receive_msg}
], InitialState).
@@ -476,7 +510,8 @@ bad_service_name_length(Config, LengthExcess) ->
%% Prohibit remote decoder starvation:
{send, #ssh_msg_service_request{name="ssh-userauth"}},
{match, {'or',[#ssh_msg_disconnect{_='_'},
- tcp_closed
+ tcp_closed,
+ {tcp_error,econnaborted}
]},
receive_msg}
], InitialState).
diff --git a/lib/ssh/test/ssh_renegotiate_SUITE.erl b/lib/ssh/test/ssh_renegotiate_SUITE.erl
index ef631d54bd..e5cfa58bad 100644
--- a/lib/ssh/test/ssh_renegotiate_SUITE.erl
+++ b/lib/ssh/test/ssh_renegotiate_SUITE.erl
@@ -32,9 +32,15 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
-all() -> [rekey, rekey_limit, renegotiate1, renegotiate2].
+all() -> [{group,default_algs},
+ {group,aes_gcm}
+ ].
-groups() -> [].
+groups() -> [{default_algs, [], tests()},
+ {aes_gcm, [], tests()}
+ ].
+
+tests() -> [rekey, rekey_limit, renegotiate1, renegotiate2].
%%--------------------------------------------------------------------
init_per_suite(Config) ->
@@ -50,6 +56,24 @@ end_per_suite(_Config) ->
crypto:stop().
%%--------------------------------------------------------------------
+init_per_group(aes_gcm, Config) ->
+ case lists:member({client2server,['[email protected]']},
+ ssh_transport:supported_algorithms(cipher)) of
+ true ->
+ [{preferred_algorithms, [{cipher,[{client2server,['[email protected]']},
+ {server2client,['[email protected]']}]}]}
+ | Config];
+ false ->
+ {skip, "aes_gcm not supported"}
+ end;
+init_per_group(_, Config) ->
+ [{preferred_algorithms, ssh:default_algorithms()} | Config].
+
+
+end_per_group(_, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
init_per_testcase(_TestCase, Config) ->
ssh:start(),
Config.
@@ -89,7 +113,9 @@ rekey_limit(Config) ->
UserDir = ?config(priv_dir, Config),
DataFile = filename:join(UserDir, "rekey.data"),
- {Pid, Host, Port} = ssh_test_lib:std_daemon(Config,[{max_random_length_padding,0}]),
+ Algs = ?config(preferred_algorithms, Config),
+ {Pid, Host, Port} = ssh_test_lib:std_daemon(Config,[{max_random_length_padding,0},
+ {preferred_algorithms,Algs}]),
ConnectionRef = ssh_test_lib:std_connect(Config, Host, Port, [{rekey_limit, 6000},
{max_random_length_padding,0}]),
@@ -133,7 +159,9 @@ renegotiate1(Config) ->
UserDir = ?config(priv_dir, Config),
DataFile = filename:join(UserDir, "renegotiate1.data"),
- {Pid, Host, DPort} = ssh_test_lib:std_daemon(Config,[{max_random_length_padding,0}]),
+ Algs = ?config(preferred_algorithms, Config),
+ {Pid, Host, DPort} = ssh_test_lib:std_daemon(Config,[{max_random_length_padding,0},
+ {preferred_algorithms,Algs}]),
RPort = ssh_test_lib:inet_port(),
{ok,RelayPid} = ssh_relay:start_link({0,0,0,0}, RPort, Host, DPort),
@@ -171,7 +199,9 @@ renegotiate2(Config) ->
UserDir = ?config(priv_dir, Config),
DataFile = filename:join(UserDir, "renegotiate2.data"),
- {Pid, Host, DPort} = ssh_test_lib:std_daemon(Config,[{max_random_length_padding,0}]),
+ Algs = ?config(preferred_algorithms, Config),
+ {Pid, Host, DPort} = ssh_test_lib:std_daemon(Config,[{max_random_length_padding,0},
+ {preferred_algorithms,Algs}]),
RPort = ssh_test_lib:inet_port(),
{ok,RelayPid} = ssh_relay:start_link({0,0,0,0}, RPort, Host, DPort),
diff --git a/lib/ssh/test/ssh_test_lib.erl b/lib/ssh/test/ssh_test_lib.erl
index 5816b708f2..ed76f4f795 100644
--- a/lib/ssh/test/ssh_test_lib.erl
+++ b/lib/ssh/test/ssh_test_lib.erl
@@ -296,7 +296,7 @@ setup_dsa(DataDir, UserDir) ->
file:make_dir(System),
file:copy(filename:join(DataDir, "ssh_host_dsa_key"), filename:join(System, "ssh_host_dsa_key")),
file:copy(filename:join(DataDir, "ssh_host_dsa_key.pub"), filename:join(System, "ssh_host_dsa_key.pub")),
-ct:pal("DataDir ~p:~n ~p~n~nSystDir ~p:~n ~p~n~nUserDir ~p:~n ~p",[DataDir, file:list_dir(DataDir), System, file:list_dir(System), UserDir, file:list_dir(UserDir)]),
+ct:log("DataDir ~p:~n ~p~n~nSystDir ~p:~n ~p~n~nUserDir ~p:~n ~p",[DataDir, file:list_dir(DataDir), System, file:list_dir(System), UserDir, file:list_dir(UserDir)]),
setup_dsa_known_host(DataDir, UserDir),
setup_dsa_auth_keys(DataDir, UserDir).
@@ -306,7 +306,7 @@ setup_rsa(DataDir, UserDir) ->
file:make_dir(System),
file:copy(filename:join(DataDir, "ssh_host_rsa_key"), filename:join(System, "ssh_host_rsa_key")),
file:copy(filename:join(DataDir, "ssh_host_rsa_key.pub"), filename:join(System, "ssh_host_rsa_key.pub")),
-ct:pal("DataDir ~p:~n ~p~n~nSystDir ~p:~n ~p~n~nUserDir ~p:~n ~p",[DataDir, file:list_dir(DataDir), System, file:list_dir(System), UserDir, file:list_dir(UserDir)]),
+ct:log("DataDir ~p:~n ~p~n~nSystDir ~p:~n ~p~n~nUserDir ~p:~n ~p",[DataDir, file:list_dir(DataDir), System, file:list_dir(System), UserDir, file:list_dir(UserDir)]),
setup_rsa_known_host(DataDir, UserDir),
setup_rsa_auth_keys(DataDir, UserDir).
@@ -316,7 +316,7 @@ setup_ecdsa(Size, DataDir, UserDir) ->
file:make_dir(System),
file:copy(filename:join(DataDir, "ssh_host_ecdsa_key"++Size), filename:join(System, "ssh_host_ecdsa_key")),
file:copy(filename:join(DataDir, "ssh_host_ecdsa_key"++Size++".pub"), filename:join(System, "ssh_host_ecdsa_key.pub")),
-ct:pal("DataDir ~p:~n ~p~n~nSystDir ~p:~n ~p~n~nUserDir ~p:~n ~p",[DataDir, file:list_dir(DataDir), System, file:list_dir(System), UserDir, file:list_dir(UserDir)]),
+ct:log("DataDir ~p:~n ~p~n~nSystDir ~p:~n ~p~n~nUserDir ~p:~n ~p",[DataDir, file:list_dir(DataDir), System, file:list_dir(System), UserDir, file:list_dir(UserDir)]),
setup_ecdsa_known_host(Size, System, UserDir),
setup_ecdsa_auth_keys(Size, UserDir, UserDir).
@@ -502,7 +502,7 @@ default_algorithms(sshd, Host, Port) ->
{user_interaction, false}]}]))
catch
_C:_E ->
- ct:pal("***~p:~p: ~p:~p",[?MODULE,?LINE,_C,_E]),
+ ct:log("***~p:~p: ~p:~p",[?MODULE,?LINE,_C,_E]),
[]
end.
@@ -522,7 +522,7 @@ default_algorithms(sshc, DaemonOptions) ->
InitialState))
catch
_C:_E ->
- ct:pal("***~p:~p: ~p:~p",[?MODULE,?LINE,_C,_E]),
+ ct:log("***~p:~p: ~p:~p",[?MODULE,?LINE,_C,_E]),
[]
end}
end),
@@ -646,3 +646,15 @@ ssh_supports(Alg, SshDefaultAlg_tag) ->
{false,UnSup}
end
end.
+
+%%%----------------------------------------------------------------
+has_inet6_address() ->
+ try
+ [throw(6) || {ok,L} <- [inet:getifaddrs()],
+ {_,L1} <- L,
+ {addr,{_,_,_,_,_,_,_,_}} <- L1]
+ of
+ [] -> false
+ catch
+ throw:6 -> true
+ end.
diff --git a/lib/ssh/test/ssh_to_openssh_SUITE.erl b/lib/ssh/test/ssh_to_openssh_SUITE.erl
index d1dfa2efdf..02cc79e4d5 100644
--- a/lib/ssh/test/ssh_to_openssh_SUITE.erl
+++ b/lib/ssh/test/ssh_to_openssh_SUITE.erl
@@ -96,19 +96,9 @@ end_per_group(_, Config) ->
init_per_testcase(erlang_server_openssh_client_public_key_dsa, Config) ->
- case ssh_test_lib:openssh_supports(sshc, public_key, 'ssh-dss') of
- true ->
- init_per_testcase('__default__',Config);
- false ->
- {skip,"openssh client does not support DSA"}
- end;
+ chk_key(sshc, 'ssh-dss', ".ssh/id_dsa", Config);
init_per_testcase(erlang_client_openssh_server_publickey_dsa, Config) ->
- case ssh_test_lib:openssh_supports(sshd, public_key, 'ssh-dss') of
- true ->
- init_per_testcase('__default__',Config);
- false ->
- {skip,"openssh client does not support DSA"}
- end;
+ chk_key(sshd, 'ssh-dss', ".ssh/id_dsa", Config);
init_per_testcase(_TestCase, Config) ->
ssh:start(),
Config.
@@ -117,6 +107,27 @@ end_per_testcase(_TestCase, _Config) ->
ssh:stop(),
ok.
+
+chk_key(Pgm, Name, File, Config) ->
+ case ssh_test_lib:openssh_supports(Pgm, public_key, Name) of
+ true ->
+ {skip,lists:concat(["openssh client does not support ",Name])};
+ false ->
+ {ok,[[Home]]} = init:get_argument(home),
+ KeyFile = filename:join(Home, File),
+ case file:read_file(KeyFile) of
+ {ok, Pem} ->
+ case public_key:pem_decode(Pem) of
+ [{_,_, not_encrypted}] ->
+ init_per_testcase('__default__',Config);
+ _ ->
+ {skip, {error, "Has pass phrase can not be used by automated test case"}}
+ end;
+ _ ->
+ {skip, lists:concat(["no ~/",File])}
+ end
+ end.
+
%%--------------------------------------------------------------------
%% Test Cases --------------------------------------------------------
%%--------------------------------------------------------------------
@@ -328,27 +339,16 @@ erlang_client_openssh_server_publickey_rsa(Config) when is_list(Config) ->
erlang_client_openssh_server_publickey_dsa() ->
[{doc, "Validate using dsa publickey."}].
erlang_client_openssh_server_publickey_dsa(Config) when is_list(Config) ->
- {ok,[[Home]]} = init:get_argument(home),
- KeyFile = filename:join(Home, ".ssh/id_dsa"),
- case file:read_file(KeyFile) of
- {ok, Pem} ->
- case public_key:pem_decode(Pem) of
- [{_,_, not_encrypted}] ->
- ConnectionRef =
- ssh_test_lib:connect(?SSH_DEFAULT_PORT,
- [{public_key_alg, ssh_dsa},
- {user_interaction, false},
- silently_accept_hosts]),
- {ok, Channel} =
- ssh_connection:session_channel(ConnectionRef, infinity),
- ok = ssh_connection:close(ConnectionRef, Channel),
- ok = ssh:close(ConnectionRef);
- _ ->
- {skip, {error, "Has pass phrase can not be used by automated test case"}}
- end;
- _ ->
- {skip, "no ~/.ssh/id_dsa"}
- end.
+ ConnectionRef =
+ ssh_test_lib:connect(?SSH_DEFAULT_PORT,
+ [{public_key_alg, ssh_dsa},
+ {user_interaction, false},
+ silently_accept_hosts]),
+ {ok, Channel} =
+ ssh_connection:session_channel(ConnectionRef, infinity),
+ ok = ssh_connection:close(ConnectionRef, Channel),
+ ok = ssh:close(ConnectionRef).
+
%%--------------------------------------------------------------------
erlang_server_openssh_client_public_key_dsa() ->
[{doc, "Validate using dsa publickey."}].
@@ -360,21 +360,25 @@ erlang_server_openssh_client_public_key_dsa(Config) when is_list(Config) ->
{Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},
{public_key_alg, ssh_dsa},
{failfun, fun ssh_test_lib:failfun/2}]),
-
+
ct:sleep(500),
Cmd = "ssh -p " ++ integer_to_list(Port) ++
" -o UserKnownHostsFile=" ++ KnownHosts ++
" " ++ Host ++ " 1+1.",
- SshPort = open_port({spawn, Cmd}, [binary]),
+ SshPort = open_port({spawn, Cmd}, [binary, stderr_to_stdout]),
receive
- {SshPort,{data, <<"2\n">>}} ->
+ {SshPort,{data, <<"2\n">>}} ->
ok
after ?TIMEOUT ->
- ct:fail("Did not receive answer")
+ receive
+ X -> ct:fail("Received: ~p",[X])
+ after 0 ->
+ ct:fail("Did not receive answer")
+ end
end,
- ssh:stop_daemon(Pid).
+ ssh:stop_daemon(Pid).
%%--------------------------------------------------------------------
erlang_client_openssh_server_password() ->
@@ -384,10 +388,10 @@ erlang_client_openssh_server_password(Config) when is_list(Config) ->
UserDir = ?config(data_dir, Config),
{error, Reason0} =
ssh:connect(any, ?SSH_DEFAULT_PORT, [{silently_accept_hosts, true},
- {user, "foo"},
- {password, "morot"},
- {user_interaction, false},
- {user_dir, UserDir}]),
+ {user, "foo"},
+ {password, "morot"},
+ {user_interaction, false},
+ {user_dir, UserDir}]),
ct:log("Test of user foo that does not exist. "
"Error msg: ~p~n", [Reason0]),
diff --git a/lib/ssh/vsn.mk b/lib/ssh/vsn.mk
index d828bccd29..25b19133b1 100644
--- a/lib/ssh/vsn.mk
+++ b/lib/ssh/vsn.mk
@@ -1,4 +1,5 @@
#-*-makefile-*- ; force emacs to enter makefile-mode
SSH_VSN = 4.2
+
APP_VSN = "ssh-$(SSH_VSN)"
diff --git a/lib/ssl/doc/src/notes.xml b/lib/ssl/doc/src/notes.xml
index 6faa3d5f9a..4d4a219b4f 100644
--- a/lib/ssl/doc/src/notes.xml
+++ b/lib/ssl/doc/src/notes.xml
@@ -26,8 +26,9 @@
<file>notes.xml</file>
</header>
<p>This document describes the changes made to the SSL application.</p>
- <section><title>SSL 7.1</title>
+
+<section><title>SSL 7.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
<item>
@@ -107,12 +108,6 @@
<p>
Own Id: OTP-12815</p>
</item>
- <item>
- <p>
- Gracefully ignore proprietary hash_sign algorithms</p>
- <p>
- Own Id: OTP-12829</p>
- </item>
</list>
</section>
@@ -163,6 +158,20 @@
</section>
+<section><title>SSL 6.0.1.1</title>
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Gracefully ignore proprietary hash_sign algorithms</p>
+ <p>
+ Own Id: OTP-12829</p>
+ </item>
+ </list>
+ </section>
+</section>
+
+
<section><title>SSL 6.0.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/ssl/doc/src/ssl.xml b/lib/ssl/doc/src/ssl.xml
index 22ac98c24e..bf87644116 100644
--- a/lib/ssl/doc/src/ssl.xml
+++ b/lib/ssl/doc/src/ssl.xml
@@ -31,37 +31,13 @@
<module>ssl</module>
<modulesummary>Interface Functions for Secure Socket Layer</modulesummary>
<description>
- <p>This module contains interface functions for the SSL.</p>
+ <p>
+ This module contains interface functions for the SSL/TLS protocol.
+ For detailed information about the supported standards see
+ <seealso marker="ssl_app">ssl(6)</seealso>.
+ </p>
</description>
-
- <section>
- <title>SSL</title>
-
- <list type="bulleted">
- <item>For application dependencies see <seealso marker="ssl_app"> ssl(6)</seealso> </item>
- <item>Supported SSL/TLS-versions are SSL-3.0, TLS-1.0,
- TLS-1.1, and TLS-1.2.</item>
- <item>For security reasons SSL-2.0 is not supported.</item>
- <item>For security reasons SSL-3.0 is no longer supported by default,
- but can be configured.</item>
- <item>Ephemeral Diffie-Hellman cipher suites are supported,
- but not Diffie Hellman Certificates cipher suites.</item>
- <item>Elliptic Curve cipher suites are supported if the Crypto
- application supports it and named curves are used.
- </item>
- <item>Export cipher suites are not supported as the
- U.S. lifted its export restrictions in early 2000.</item>
- <item>IDEA cipher suites are not supported as they have
- become deprecated by the latest TLS specification so it is not
- motivated to implement them.</item>
- <item>CRL validation is supported.</item>
- <item>Policy certificate extensions are not supported.</item>
- <item>'Server Name Indication' extension client side
- (RFC 6066, Section 3) is supported.</item>
- </list>
-
- </section>
-
+
<section>
<title>DATA TYPES</title>
<p>The following data types are used in the functions for SSL:</p>
@@ -84,7 +60,7 @@
<seealso marker="kernel:gen_tcp">gen_tcp(3)</seealso> manual pages
in Kernel.</p></item>
- <tag><marker id="type-ssloption"></marker><c>ssloption() =</c></tag>
+ <tag><marker id="type-ssloption"/><c>ssloption() =</c></tag>
<item>
<p><c>{verify, verify_type()}</c></p>
<p><c>| {verify_fun, {fun(), term()}}</c></p>
@@ -160,7 +136,7 @@
<tag><c>sslsocket() =</c></tag>
<item><p>opaque()</p></item>
- <tag><c>protocol() =</c></tag>
+ <tag><marker id="type-protocol"/><c>protocol() =</c></tag>
<item><p><c>sslv3 | tlsv1 | 'tlsv1.1' | 'tlsv1.2'</c></p></item>
<tag><c>ciphers() =</c></tag>
@@ -480,8 +456,8 @@ fun(srp, Username :: string(), UserState :: term()) ->
<p>The negotiated protocol can be retrieved using the <c>negotiated_protocol/1</c> function.</p>
</item>
- <tag><c>{client_preferred_next_protocols, {Precedence :: server | client, ClientPrefs :: [binary()]}}</c></tag>
- <tag><c>{client_preferred_next_protocols, {Precedence :: server | client, ClientPrefs :: [binary()], Default :: binary()}}</c></tag>
+ <tag><c>{client_preferred_next_protocols, {Precedence :: server | client, ClientPrefs :: [binary()]}}</c><br/>
+ <c>{client_preferred_next_protocols, {Precedence :: server | client, ClientPrefs :: [binary()], Default :: binary()}}</c></tag>
<item>
<p>Indicates that the client is to try to perform Next Protocol
Negotiation.</p>
@@ -538,7 +514,6 @@ fun(srp, Username :: string(), UserState :: term()) ->
be supported by the server for the prevention to work.
</p></warning>
</item>
-
</taglist>
</section>
diff --git a/lib/ssl/doc/src/ssl_app.xml b/lib/ssl/doc/src/ssl_app.xml
index 51ce0cedf1..6c82e32a74 100644
--- a/lib/ssl/doc/src/ssl_app.xml
+++ b/lib/ssl/doc/src/ssl_app.xml
@@ -33,7 +33,33 @@
<appsummary>The ssl application provides secure communication over
sockets.</appsummary>
- <description></description>
+ <description>
+ <p>
+ The ssl application is an implementation of the SSL/TLS protocol in Erlang.
+ </p>
+ <list type="bulleted">
+ <item>Supported SSL/TLS-versions are SSL-3.0, TLS-1.0,
+ TLS-1.1, and TLS-1.2.</item>
+ <item>For security reasons SSL-2.0 is not supported.</item>
+ <item>For security reasons SSL-3.0 is no longer supported by default,
+ but can be configured.</item>
+ <item>Ephemeral Diffie-Hellman cipher suites are supported,
+ but not Diffie Hellman Certificates cipher suites.</item>
+ <item>Elliptic Curve cipher suites are supported if the Crypto
+ application supports it and named curves are used.
+ </item>
+ <item>Export cipher suites are not supported as the
+ U.S. lifted its export restrictions in early 2000.</item>
+ <item>IDEA cipher suites are not supported as they have
+ become deprecated by the latest TLS specification so it is not
+ motivated to implement them.</item>
+ <item>CRL validation is supported.</item>
+ <item>Policy certificate extensions are not supported.</item>
+ <item>'Server Name Indication' extension client side
+ (RFC 6066, Section 3) is supported.</item>
+ </list>
+ </description>
+
<section>
<title>DEPENDENCIES</title>
<p>The SSL application uses the <c>public_key</c> and
@@ -58,7 +84,7 @@
<p><c>erl -ssl protocol_version "['tlsv1.2', 'tlsv1.1']"</c></p>
<taglist>
- <tag><c><![CDATA[protocol_version = <seealso marker="kernel:error_logger">ssl:protocol()</seealso> <optional>]]></c>.</tag>
+ <tag><c>protocol_version = </c><seealso marker="ssl#type-protocol">ssl:protocol()</seealso><c><![CDATA[<optional>]]></c></tag>
<item><p>Protocol supported by started clients and
servers. If this option is not set, it defaults to all
protocols currently supported by the SSL application.
@@ -66,17 +92,24 @@
to <c>ssl:connect/[2,3]</c> and <c>ssl:listen/2</c>.</p></item>
<tag><c><![CDATA[session_lifetime = integer() <optional>]]></c></tag>
- <item><p>Lifetime of the session data in seconds.</p></item>
+ <item><p>Maximum lifetime of the session data in seconds.</p></item>
<tag><c><![CDATA[session_cb = atom() <optional>]]></c></tag>
<item><p>Name of the session cache callback module that implements
the <c>ssl_session_cache_api</c> behavior. Defaults to
- <c>ssl_session_cache.erl</c>.</p></item>
+ <c>ssl_session_cache</c>.</p></item>
<tag><c><![CDATA[session_cb_init_args = proplist:proplist() <optional>]]></c></tag>
<item><p>List of extra user-defined arguments to the <c>init</c> function
in the session cache callback module. Defaults to <c>[]</c>.</p></item>
+
+ <tag><c><![CDATA[session_cache_client_max = integer() <optional>]]></c><br/>
+ <c><![CDATA[session_cache_server_max = integer() <optional>]]></c></tag>
+ <item><p>Limits the growth of the clients/servers session cache,
+ if the maximum number of sessions is reached, the current cache entries will
+ be invalidated regardless of their remaining lifetime. Defaults to 1000.
+ </p></item>
<tag><c><![CDATA[ssl_pem_cache_clean = integer() <optional>]]></c></tag>
<item>
@@ -103,7 +136,10 @@
<section>
<title>ERROR LOGGER AND EVENT HANDLERS</title>
- <p>The SSL application uses the default <seealso marker="kernel:error_logger">OTP error logger</seealso> to log unexpected errors and TLS alerts. The logging of TLS alerts may be turned off with the <c>log_alert</c> option. </p>
+ <p>The SSL application uses the default <seealso
+ marker="kernel:error_logger">OTP error logger</seealso> to log
+ unexpected errors and TLS alerts. The logging of TLS alerts may be
+ turned off with the <c>log_alert</c> option. </p>
</section>
<section>
diff --git a/lib/ssl/doc/src/ssl_crl_cache_api.xml b/lib/ssl/doc/src/ssl_crl_cache_api.xml
index 71c1c61fe8..03ac010bfe 100644
--- a/lib/ssl/doc/src/ssl_crl_cache_api.xml
+++ b/lib/ssl/doc/src/ssl_crl_cache_api.xml
@@ -84,9 +84,9 @@
<v> CRLs = [<seealso
marker="public_key:public_key">public_key:der_encoded()</seealso>] </v>
</type>
- <desc> <p>Lookup the CRLs belonging to the distribution point <c> Distributionpoint</c>. </p>
+ <desc> <p>Lookup the CRLs belonging to the distribution point <c> Distributionpoint</c>.
This function may choose to only look in the cache or to follow distribution point
- links depending on how the cache is administrated.
+ links depending on how the cache is administrated. </p>
</desc>
</func>
@@ -103,4 +103,4 @@
</desc>
</func>
</funcs>
-</erlref> \ No newline at end of file
+</erlref>
diff --git a/lib/ssl/doc/src/ssl_session_cache_api.xml b/lib/ssl/doc/src/ssl_session_cache_api.xml
index bd9330056d..b85d8fb284 100644
--- a/lib/ssl/doc/src/ssl_session_cache_api.xml
+++ b/lib/ssl/doc/src/ssl_session_cache_api.xml
@@ -31,9 +31,13 @@
<module>ssl_session_cache_api</module>
<modulesummary>TLS session cache API</modulesummary>
- <description>Defines the API for the TLS session cache so
- that the data storage scheme can be replaced by
- defining a new callback module implementing this API.</description>
+ <description>
+ <p>
+ Defines the API for the TLS session cache so
+ that the data storage scheme can be replaced by
+ defining a new callback module implementing this API.
+ </p>
+ </description>
<section>
<title>DATA TYPES</title>
diff --git a/lib/ssl/src/dtls_connection.erl b/lib/ssl/src/dtls_connection.erl
index 78662e0ea2..153d3fef48 100644
--- a/lib/ssl/src/dtls_connection.erl
+++ b/lib/ssl/src/dtls_connection.erl
@@ -145,7 +145,7 @@ init([Role, Host, Port, Socket, {SSLOpts0, _} = Options, User, CbInfo]) ->
process_flag(trap_exit, true),
State0 = initial_state(Role, Host, Port, Socket, Options, User, CbInfo),
Handshake = ssl_handshake:init_handshake_history(),
- TimeStamp = calendar:datetime_to_gregorian_seconds({date(), time()}),
+ TimeStamp = erlang:monotonic_time(),
try ssl_config:init(SSLOpts0, Role) of
{ok, Ref, CertDbHandle, FileRefHandle, CacheHandle, CRLDbInfo, OwnCert, Key, DHParams} ->
Session = State0#state.session,
diff --git a/lib/ssl/src/inet_tls_dist.erl b/lib/ssl/src/inet_tls_dist.erl
index b6e62a18c9..404ae93d20 100644
--- a/lib/ssl/src/inet_tls_dist.erl
+++ b/lib/ssl/src/inet_tls_dist.erl
@@ -30,7 +30,7 @@
childspecs() ->
{ok, [{ssl_dist_sup,{ssl_dist_sup, start_link, []},
- permanent, 2000, worker, [ssl_dist_sup]}]}.
+ permanent, infinity, supervisor, [ssl_dist_sup]}]}.
select(Node) ->
case split_node(atom_to_list(Node), $@, []) of
diff --git a/lib/ssl/src/ssl.app.src b/lib/ssl/src/ssl.app.src
index be8ef6f85f..619ab7b610 100644
--- a/lib/ssl/src/ssl.app.src
+++ b/lib/ssl/src/ssl.app.src
@@ -54,6 +54,6 @@
{env, []},
{mod, {ssl_app, []}},
{runtime_dependencies, ["stdlib-2.0","public_key-1.0","kernel-3.0",
- "erts-6.0","crypto-3.3", "inets-5.10.7"]}]}.
+ "erts-7.0","crypto-3.3", "inets-5.10.7"]}]}.
diff --git a/lib/ssl/src/ssl.appup.src b/lib/ssl/src/ssl.appup.src
index 8d5bd6f8d8..11728128c4 100644
--- a/lib/ssl/src/ssl.appup.src
+++ b/lib/ssl/src/ssl.appup.src
@@ -1,24 +1,14 @@
%% -*- erlang -*-
{"%VSN%",
[
- {<<"7\\.0">>, [{load_module, ssl, soft_purge, soft_purge, []},
- {load_module, ssl_connection, soft_purge, soft_purge, []},
- {load_module, tls_connection, soft_purge, soft_purge, []},
- {load_module, ssl_session, soft_purge, soft_purge, []},
- {load_module, ssl_session_cache, soft_purge, soft_purge, []}
- ]},
+ {<<"7\\..*">>, [{restart_application, ssl}]},
{<<"6\\..*">>, [{restart_application, ssl}]},
{<<"5\\..*">>, [{restart_application, ssl}]},
{<<"4\\..*">>, [{restart_application, ssl}]},
{<<"3\\..*">>, [{restart_application, ssl}]}
],
[
- {<<"7\\.0">>, [{load_module, ssl, soft_purge, soft_purge, []},
- {load_module, ssl_connection, soft_purge, soft_purge, []},
- {load_module, tls_connection, soft_purge, soft_purge, []},
- {load_module, ssl_session, soft_purge, soft_purge, []},
- {load_module, ssl_session_cache, soft_purge, soft_purge, []}
- ]},
+ {<<"7\\..*">>, [{restart_application, ssl}]},
{<<"6\\..*">>, [{restart_application, ssl}]},
{<<"5\\..*">>, [{restart_application, ssl}]},
{<<"4\\..*">>, [{restart_application, ssl}]},
diff --git a/lib/ssl/src/ssl.erl b/lib/ssl/src/ssl.erl
index 03495cfd90..6551308935 100644
--- a/lib/ssl/src/ssl.erl
+++ b/lib/ssl/src/ssl.erl
@@ -1190,6 +1190,8 @@ assert_proplist([]) ->
assert_proplist([{Key,_} | Rest]) when is_atom(Key) ->
assert_proplist(Rest);
%% Handle exceptions
+assert_proplist([{raw,_,_,_} | Rest]) ->
+ assert_proplist(Rest);
assert_proplist([inet | Rest]) ->
assert_proplist(Rest);
assert_proplist([inet6 | Rest]) ->
diff --git a/lib/ssl/src/ssl_connection.erl b/lib/ssl/src/ssl_connection.erl
index f8afbdb41d..241871dc38 100644
--- a/lib/ssl/src/ssl_connection.erl
+++ b/lib/ssl/src/ssl_connection.erl
@@ -974,7 +974,7 @@ ssl_config(Opts, Role, State) ->
{ok, Ref, CertDbHandle, FileRefHandle, CacheHandle, CRLDbInfo, OwnCert, Key, DHParams} =
ssl_config:init(Opts, Role),
Handshake = ssl_handshake:init_handshake_history(),
- TimeStamp = calendar:datetime_to_gregorian_seconds({date(), time()}),
+ TimeStamp = erlang:monotonic_time(),
Session = State#state.session,
State#state{tls_handshake_history = Handshake,
session = Session#session{own_certificate = OwnCert,
@@ -1781,7 +1781,7 @@ handle_trusted_certs_db(#state{ssl_options = #ssl_options{cacertfile = <<>>, cac
ok;
handle_trusted_certs_db(#state{cert_db_ref = Ref,
cert_db = CertDb,
- ssl_options = #ssl_options{cacertfile = <<>>}}) ->
+ ssl_options = #ssl_options{cacertfile = <<>>}}) when CertDb =/= undefined ->
%% Certs provided as DER directly can not be shared
%% with other connections and it is safe to delete them when the connection ends.
ssl_pkix_db:remove_trusted_certs(Ref, CertDb);
diff --git a/lib/ssl/src/ssl_dist_sup.erl b/lib/ssl/src/ssl_dist_sup.erl
index aa1fa57db8..435ad27a44 100644
--- a/lib/ssl/src/ssl_dist_sup.erl
+++ b/lib/ssl/src/ssl_dist_sup.erl
@@ -70,7 +70,7 @@ connection_manager_child_spec() ->
Name = ssl_connection_dist,
StartFunc = {tls_connection_sup, start_link_dist, []},
Restart = permanent,
- Shutdown = 4000,
+ Shutdown = infinity,
Modules = [tls_connection_sup],
Type = supervisor,
{Name, StartFunc, Restart, Shutdown, Type, Modules}.
diff --git a/lib/ssl/src/ssl_internal.hrl b/lib/ssl/src/ssl_internal.hrl
index 007723c982..913746598f 100644
--- a/lib/ssl/src/ssl_internal.hrl
+++ b/lib/ssl/src/ssl_internal.hrl
@@ -78,6 +78,9 @@
-define(ALL_DATAGRAM_SUPPORTED_VERSIONS, ['dtlsv1.2', dtlsv1]).
-define(MIN_DATAGRAM_SUPPORTED_VERSIONS, ['dtlsv1.2', dtlsv1]).
+-define('24H_in_msec', 86400000).
+-define('24H_in_sec', 86400).
+
-record(ssl_options, {
protocol :: tls | dtls,
versions :: [ssl_record:ssl_version()], %% ssl_record:atom_version() in API
diff --git a/lib/ssl/src/ssl_manager.erl b/lib/ssl/src/ssl_manager.erl
index 2e05ba5aa5..00e95f5c5b 100644
--- a/lib/ssl/src/ssl_manager.erl
+++ b/lib/ssl/src/ssl_manager.erl
@@ -46,25 +46,27 @@
-include_lib("kernel/include/file.hrl").
-record(state, {
- session_cache_client,
- session_cache_server,
- session_cache_cb,
- session_lifetime,
- certificate_db,
- session_validation_timer,
+ session_cache_client :: db_handle(),
+ session_cache_server :: db_handle(),
+ session_cache_cb :: atom(),
+ session_lifetime :: integer(),
+ certificate_db :: db_handle(),
+ session_validation_timer :: reference(),
last_delay_timer = {undefined, undefined},%% Keep for testing purposes
- last_pem_check,
- clear_pem_cache
+ last_pem_check :: erlang:timestamp(),
+ clear_pem_cache :: integer(),
+ session_cache_client_max :: integer(),
+ session_cache_server_max :: integer(),
+ session_server_invalidator :: undefined | pid(),
+ session_client_invalidator :: undefined | pid()
}).
--define('24H_in_msec', 86400000).
--define('24H_in_sec', 86400).
-define(GEN_UNIQUE_ID_MAX_TRIES, 10).
-define(SESSION_VALIDATION_INTERVAL, 60000).
-define(CLEAR_PEM_CACHE, 120000).
-define(CLEAN_SESSION_DB, 60000).
-define(CLEAN_CERT_DB, 500).
--define(NOT_TO_BIG, 10).
+-define(DEFAULT_MAX_SESSION_CACHE, 1000).
%%====================================================================
%% API
@@ -89,7 +91,8 @@ manager_name(dist) ->
%%--------------------------------------------------------------------
start_link(Opts) ->
DistMangerName = manager_name(normal),
- gen_server:start_link({local, DistMangerName}, ?MODULE, [DistMangerName, Opts], []).
+ gen_server:start_link({local, DistMangerName},
+ ?MODULE, [DistMangerName, Opts], []).
%%--------------------------------------------------------------------
-spec start_link_dist(list()) -> {ok, pid()} | ignore | {error, term()}.
@@ -99,7 +102,8 @@ start_link(Opts) ->
%%--------------------------------------------------------------------
start_link_dist(Opts) ->
DistMangerName = manager_name(dist),
- gen_server:start_link({local, DistMangerName}, ?MODULE, [DistMangerName, Opts], []).
+ gen_server:start_link({local, DistMangerName},
+ ?MODULE, [DistMangerName, Opts], []).
%%--------------------------------------------------------------------
-spec connection_init(binary()| {der, list()}, client | server,
@@ -169,7 +173,8 @@ new_session_id(Port) ->
%% be called by ssl-connection processes.
%%--------------------------------------------------------------------
clean_cert_db(Ref, File) ->
- erlang:send_after(?CLEAN_CERT_DB, get(ssl_manager), {clean_cert_db, Ref, File}),
+ erlang:send_after(?CLEAN_CERT_DB, get(ssl_manager),
+ {clean_cert_db, Ref, File}),
ok.
%%--------------------------------------------------------------------
@@ -237,10 +242,12 @@ init([Name, Opts]) ->
SessionLifeTime =
proplists:get_value(session_lifetime, Opts, ?'24H_in_sec'),
CertDb = ssl_pkix_db:create(),
- ClientSessionCache = CacheCb:init([{role, client} |
- proplists:get_value(session_cb_init_args, Opts, [])]),
- ServerSessionCache = CacheCb:init([{role, server} |
- proplists:get_value(session_cb_init_args, Opts, [])]),
+ ClientSessionCache =
+ CacheCb:init([{role, client} |
+ proplists:get_value(session_cb_init_args, Opts, [])]),
+ ServerSessionCache =
+ CacheCb:init([{role, server} |
+ proplists:get_value(session_cb_init_args, Opts, [])]),
Timer = erlang:send_after(SessionLifeTime * 1000 + 5000,
self(), validate_sessions),
Interval = pem_check_interval(),
@@ -252,7 +259,11 @@ init([Name, Opts]) ->
session_lifetime = SessionLifeTime,
session_validation_timer = Timer,
last_pem_check = os:timestamp(),
- clear_pem_cache = Interval
+ clear_pem_cache = Interval,
+ session_cache_client_max =
+ max_session_cache_size(session_cache_client_max),
+ session_cache_server_max =
+ max_session_cache_size(session_cache_server_max)
}}.
%%--------------------------------------------------------------------
@@ -269,7 +280,8 @@ init([Name, Opts]) ->
handle_call({{connection_init, <<>>, Role, {CRLCb, UserCRLDb}}, _Pid}, _From,
#state{certificate_db = [CertDb, FileRefDb, PemChace | _] = Db} = State) ->
Ref = make_ref(),
- Result = {ok, Ref, CertDb, FileRefDb, PemChace, session_cache(Role, State), {CRLCb, crl_db_info(Db, UserCRLDb)}},
+ Result = {ok, Ref, CertDb, FileRefDb, PemChace,
+ session_cache(Role, State), {CRLCb, crl_db_info(Db, UserCRLDb)}},
{reply, Result, State#state{certificate_db = Db}};
handle_call({{connection_init, Trustedcerts, Role, {CRLCb, UserCRLDb}}, Pid}, _From,
@@ -307,7 +319,8 @@ handle_call({{cache_pem,File}, _Pid}, _,
_:Reason ->
{reply, {error, Reason}, State}
end;
-handle_call({unconditionally_clear_pem_cache, _},_, #state{certificate_db = [_,_,PemChace | _]} = State) ->
+handle_call({unconditionally_clear_pem_cache, _},_,
+ #state{certificate_db = [_,_,PemChace | _]} = State) ->
ssl_pkix_db:clear(PemChace),
{reply, ok, State}.
@@ -319,27 +332,12 @@ handle_call({unconditionally_clear_pem_cache, _},_, #state{certificate_db = [_,_
%%
%% Description: Handling cast messages
%%--------------------------------------------------------------------
-handle_cast({register_session, Host, Port, Session},
- #state{session_cache_client = Cache,
- session_cache_cb = CacheCb} = State) ->
- TimeStamp = calendar:datetime_to_gregorian_seconds({date(), time()}),
- NewSession = Session#session{time_stamp = TimeStamp},
-
- case CacheCb:select_session(Cache, {Host, Port}) of
- no_session ->
- CacheCb:update(Cache, {{Host, Port},
- NewSession#session.session_id}, NewSession);
- Sessions ->
- register_unique_session(Sessions, NewSession, CacheCb, Cache, {Host, Port})
- end,
+handle_cast({register_session, Host, Port, Session}, State0) ->
+ State = ssl_client_register_session(Host, Port, Session, State0),
{noreply, State};
-handle_cast({register_session, Port, Session},
- #state{session_cache_server = Cache,
- session_cache_cb = CacheCb} = State) ->
- TimeStamp = calendar:datetime_to_gregorian_seconds({date(), time()}),
- NewSession = Session#session{time_stamp = TimeStamp},
- CacheCb:update(Cache, {Port, NewSession#session.session_id}, NewSession),
+handle_cast({register_session, Port, Session}, State0) ->
+ State = server_register_session(Port, Session, State0),
{noreply, State};
handle_cast({invalidate_session, Host, Port,
@@ -413,10 +411,10 @@ handle_info({clean_cert_db, Ref, File},
end,
{noreply, State};
-handle_info({'EXIT', _, _}, State) ->
- %% Session validator died!! Do we need to take any action?
- %% maybe error log
- {noreply, State};
+handle_info({'EXIT', Pid, _}, #state{session_client_invalidator = Pid} = State) ->
+ {noreply, State#state{session_client_invalidator = undefined}};
+handle_info({'EXIT', Pid, _}, #state{session_server_invalidator = Pid} = State) ->
+ {noreply, State#state{session_server_invalidator = undefined}};
handle_info(_Info, State) ->
{noreply, State}.
@@ -497,7 +495,15 @@ delay_time() ->
?CLEAN_SESSION_DB
end.
-invalidate_session(Cache, CacheCb, Key, Session, #state{last_delay_timer = LastTimer} = State) ->
+max_session_cache_size(CacheType) ->
+ case application:get_env(ssl, CacheType) of
+ {ok, Size} when is_integer(Size) ->
+ Size;
+ _ ->
+ ?DEFAULT_MAX_SESSION_CACHE
+ end.
+
+invalidate_session(Cache, CacheCb, Key, Session, State) ->
case CacheCb:lookup(Cache, Key) of
undefined -> %% Session is already invalidated
{noreply, State};
@@ -505,15 +511,23 @@ invalidate_session(Cache, CacheCb, Key, Session, #state{last_delay_timer = LastT
CacheCb:delete(Cache, Key),
{noreply, State};
_ ->
- %% When a registered session is invalidated we need to wait a while before deleting
- %% it as there might be pending connections that rightfully needs to look
- %% up the session data but new connections should not get to use this session.
- CacheCb:update(Cache, Key, Session#session{is_resumable = false}),
- TRef =
- erlang:send_after(delay_time(), self(), {delayed_clean_session, Key, Cache}),
- {noreply, State#state{last_delay_timer = last_delay_timer(Key, TRef, LastTimer)}}
+ delayed_invalidate_session(CacheCb, Cache, Key, Session, State)
end.
+delayed_invalidate_session(CacheCb, Cache, Key, Session,
+ #state{last_delay_timer = LastTimer} = State) ->
+ %% When a registered session is invalidated we need to
+ %% wait a while before deleting it as there might be
+ %% pending connections that rightfully needs to look up
+ %% the session data but new connections should not get to
+ %% use this session.
+ CacheCb:update(Cache, Key, Session#session{is_resumable = false}),
+ TRef =
+ erlang:send_after(delay_time(), self(),
+ {delayed_clean_session, Key, Cache}),
+ {noreply, State#state{last_delay_timer =
+ last_delay_timer(Key, TRef, LastTimer)}}.
+
last_delay_timer({{_,_},_}, TRef, {LastServer, _}) ->
{LastServer, TRef};
last_delay_timer({_,_}, TRef, {_, LastClient}) ->
@@ -532,12 +546,12 @@ new_id(Port, Tries, Cache, CacheCb) ->
Id = crypto:rand_bytes(?NUM_OF_SESSION_ID_BYTES),
case CacheCb:lookup(Cache, {Port, Id}) of
undefined ->
- Now = calendar:datetime_to_gregorian_seconds({date(), time()}),
+ Now = erlang:monotonic_time(),
%% New sessions can not be set to resumable
%% until handshake is compleate and the
%% other session values are set.
CacheCb:update(Cache, {Port, Id}, #session{session_id = Id,
- is_resumable = false,
+ is_resumable = new,
time_stamp = Now}),
Id;
_ ->
@@ -559,15 +573,62 @@ clean_cert_db(Ref, CertDb, RefDb, PemCache, File) ->
ok
end.
+ssl_client_register_session(Host, Port, Session, #state{session_cache_client = Cache,
+ session_cache_cb = CacheCb,
+ session_cache_client_max = Max,
+ session_client_invalidator = Pid0} = State) ->
+ TimeStamp = erlang:monotonic_time(),
+ NewSession = Session#session{time_stamp = TimeStamp},
+
+ case CacheCb:select_session(Cache, {Host, Port}) of
+ no_session ->
+ Pid = do_register_session({{Host, Port},
+ NewSession#session.session_id},
+ NewSession, Max, Pid0, Cache, CacheCb),
+ State#state{session_client_invalidator = Pid};
+ Sessions ->
+ register_unique_session(Sessions, NewSession, {Host, Port}, State)
+ end.
+
+server_register_session(Port, Session, #state{session_cache_server_max = Max,
+ session_cache_server = Cache,
+ session_cache_cb = CacheCb,
+ session_server_invalidator = Pid0} = State) ->
+ TimeStamp = erlang:monotonic_time(),
+ NewSession = Session#session{time_stamp = TimeStamp},
+ Pid = do_register_session({Port, NewSession#session.session_id},
+ NewSession, Max, Pid0, Cache, CacheCb),
+ State#state{session_server_invalidator = Pid}.
+
+do_register_session(Key, Session, Max, Pid, Cache, CacheCb) ->
+ try CacheCb:size(Cache) of
+ N when N > Max ->
+ invalidate_session_cache(Pid, CacheCb, Cache);
+ _ ->
+ CacheCb:update(Cache, Key, Session),
+ Pid
+ catch
+ error:undef ->
+ CacheCb:update(Cache, Key, Session),
+ Pid
+ end.
+
+
%% Do not let dumb clients create a gigantic session table
%% for itself creating big delays at connection time.
-register_unique_session(Sessions, Session, CacheCb, Cache, PartialKey) ->
+register_unique_session(Sessions, Session, PartialKey,
+ #state{session_cache_client_max = Max,
+ session_cache_client = Cache,
+ session_cache_cb = CacheCb,
+ session_client_invalidator = Pid0} = State) ->
case exists_equivalent(Session , Sessions) of
true ->
- ok;
+ State;
false ->
- CacheCb:update(Cache, {PartialKey,
- Session#session.session_id}, Session)
+ Pid = do_register_session({PartialKey,
+ Session#session.session_id},
+ Session, Max, Pid0, Cache, CacheCb),
+ State#state{session_client_invalidator = Pid}
end.
exists_equivalent(_, []) ->
@@ -622,7 +683,8 @@ pem_check_interval() ->
end.
is_before_checkpoint(Time, CheckPoint) ->
- calendar:datetime_to_gregorian_seconds(calendar:now_to_datetime(CheckPoint)) -
+ calendar:datetime_to_gregorian_seconds(
+ calendar:now_to_datetime(CheckPoint)) -
calendar:datetime_to_gregorian_seconds(Time) > 0.
add_trusted_certs(Pid, Trustedcerts, Db) ->
@@ -643,3 +705,9 @@ crl_db_info([_,_,_,Local], {internal, Info}) ->
crl_db_info(_, UserCRLDb) ->
UserCRLDb.
+%% Only start a session invalidator if there is not
+%% one already active
+invalidate_session_cache(undefined, CacheCb, Cache) ->
+ start_session_validator(Cache, CacheCb, {invalidate_before, erlang:monotonic_time()});
+invalidate_session_cache(Pid, _CacheCb, _Cache) ->
+ Pid.
diff --git a/lib/ssl/src/ssl_session.erl b/lib/ssl/src/ssl_session.erl
index 0d6cc93a20..2b24bff5ff 100644
--- a/lib/ssl/src/ssl_session.erl
+++ b/lib/ssl/src/ssl_session.erl
@@ -31,8 +31,6 @@
%% Internal application API
-export([is_new/2, client_id/4, server_id/6, valid_session/2]).
--define('24H_in_sec', 8640).
-
-type seconds() :: integer().
%%--------------------------------------------------------------------
@@ -63,13 +61,16 @@ client_id(ClientInfo, Cache, CacheCb, OwnCert) ->
SessionId
end.
--spec valid_session(#session{}, seconds()) -> boolean().
+-spec valid_session(#session{}, seconds() | {invalidate_before, integer()}) -> boolean().
%%
%% Description: Check that the session has not expired
%%--------------------------------------------------------------------
+valid_session(#session{time_stamp = TimeStamp}, {invalidate_before, Before}) ->
+ TimeStamp > Before;
valid_session(#session{time_stamp = TimeStamp}, LifeTime) ->
- Now = calendar:datetime_to_gregorian_seconds({date(), time()}),
- Now - TimeStamp < LifeTime.
+ Now = erlang:monotonic_time(),
+ Lived = erlang:convert_time_unit(Now-TimeStamp, native, seconds),
+ Lived < LifeTime.
server_id(Port, <<>>, _SslOpts, _Cert, _, _) ->
{ssl_manager:new_session_id(Port), undefined};
diff --git a/lib/ssl/src/ssl_session_cache.erl b/lib/ssl/src/ssl_session_cache.erl
index cfc48cd935..9585e613e6 100644
--- a/lib/ssl/src/ssl_session_cache.erl
+++ b/lib/ssl/src/ssl_session_cache.erl
@@ -27,7 +27,7 @@
-include("ssl_internal.hrl").
-export([init/1, terminate/1, lookup/2, update/3, delete/2, foldl/3,
- select_session/2]).
+ select_session/2, size/1]).
%%--------------------------------------------------------------------
%% Description: Return table reference. Called by ssl_manager process.
@@ -86,6 +86,12 @@ select_session(Cache, PartialKey) ->
[{{{PartialKey,'_'}, '$1'},[],['$1']}]).
%%--------------------------------------------------------------------
+%% Description: Returns the cache size
+%%--------------------------------------------------------------------
+size(Cache) ->
+ ets:info(Cache, size).
+
+%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
cache_name(Name) ->
diff --git a/lib/ssl/src/ssl_session_cache_api.erl b/lib/ssl/src/ssl_session_cache_api.erl
index 536b52c44b..8f62c25be5 100644
--- a/lib/ssl/src/ssl_session_cache_api.erl
+++ b/lib/ssl/src/ssl_session_cache_api.erl
@@ -33,3 +33,4 @@
-callback delete(db_handle(), key()) -> any().
-callback foldl(fun(), term(), db_handle()) -> term().
-callback select_session(db_handle(), {host(), inet:port_number()} | inet:port_number()) -> [#session{}].
+-callback size(db_handle()) -> integer().
diff --git a/lib/ssl/src/ssl_tls_dist_proxy.erl b/lib/ssl/src/ssl_tls_dist_proxy.erl
index 273d3b5521..d384264b53 100644
--- a/lib/ssl/src/ssl_tls_dist_proxy.erl
+++ b/lib/ssl/src/ssl_tls_dist_proxy.erl
@@ -48,6 +48,47 @@ accept(Listen) ->
connect(Ip, Port) ->
gen_server:call(?MODULE, {connect, Ip, Port}, infinity).
+
+do_listen(Options) ->
+ {First,Last} = case application:get_env(kernel,inet_dist_listen_min) of
+ {ok,N} when is_integer(N) ->
+ case application:get_env(kernel,
+ inet_dist_listen_max) of
+ {ok,M} when is_integer(M) ->
+ {N,M};
+ _ ->
+ {N,N}
+ end;
+ _ ->
+ {0,0}
+ end,
+ do_listen(First, Last, listen_options([{backlog,128}|Options])).
+
+do_listen(First,Last,_) when First > Last ->
+ {error,eaddrinuse};
+do_listen(First,Last,Options) ->
+ case gen_tcp:listen(First, Options) of
+ {error, eaddrinuse} ->
+ do_listen(First+1,Last,Options);
+ Other ->
+ Other
+ end.
+
+listen_options(Opts0) ->
+ Opts1 =
+ case application:get_env(kernel, inet_dist_use_interface) of
+ {ok, Ip} ->
+ [{ip, Ip} | Opts0];
+ _ ->
+ Opts0
+ end,
+ case application:get_env(kernel, inet_dist_listen_options) of
+ {ok,ListenOpts} ->
+ ListenOpts ++ Opts1;
+ _ ->
+ Opts1
+ end.
+
%%====================================================================
%% gen_server callbacks
%%====================================================================
@@ -62,13 +103,17 @@ init([]) ->
handle_call({listen, Name}, _From, State) ->
case gen_tcp:listen(0, [{active, false}, {packet,?PPRE}]) of
{ok, Socket} ->
- {ok, World} = gen_tcp:listen(0, [{active, false}, binary, {packet,?PPRE}]),
+ {ok, World} = do_listen([{active, false}, binary, {packet,?PPRE}, {reuseaddr, true}]),
{ok, TcpAddress} = get_tcp_address(Socket),
{ok, WorldTcpAddress} = get_tcp_address(World),
{_,Port} = WorldTcpAddress#net_address.address,
- {ok, Creation} = erl_epmd:register_node(Name, Port),
- {reply, {ok, {Socket, TcpAddress, Creation}},
- State#state{listen={Socket, World}}};
+ case erl_epmd:register_node(Name, Port) of
+ {ok, Creation} ->
+ {reply, {ok, {Socket, TcpAddress, Creation}},
+ State#state{listen={Socket, World}}};
+ {error, _} = Error ->
+ {reply, Error, State}
+ end;
Error ->
{reply, Error, State}
end;
@@ -134,6 +179,7 @@ accept_loop(Proxy, erts = Type, Listen, Extra) ->
Extra ! {accept,self(),Socket,inet,proxy},
receive
{_Kernel, controller, Pid} ->
+ inet:setopts(Socket, [nodelay()]),
ok = gen_tcp:controlling_process(Socket, Pid),
flush_old_controller(Pid, Socket),
Pid ! {self(), controller};
@@ -167,7 +213,7 @@ accept_loop(Proxy, world = Type, Listen, Extra) ->
accept_loop(Proxy, Type, Listen, Extra).
try_connect(Port) ->
- case gen_tcp:connect({127,0,0,1}, Port, [{active, false}, {packet,?PPRE}]) of
+ case gen_tcp:connect({127,0,0,1}, Port, [{active, false}, {packet,?PPRE}, nodelay()]) of
R = {ok, _S} ->
R;
{error, _R} ->
@@ -177,7 +223,7 @@ try_connect(Port) ->
setup_proxy(Ip, Port, Parent) ->
process_flag(trap_exit, true),
Opts = get_ssl_options(client),
- case ssl:connect(Ip, Port, [{active, true}, binary, {packet,?PPRE}] ++ Opts) of
+ case ssl:connect(Ip, Port, [{active, true}, binary, {packet,?PPRE}, nodelay()] ++ Opts) of
{ok, World} ->
{ok, ErtsL} = gen_tcp:listen(0, [{active, true}, {ip, {127,0,0,1}}, binary, {packet,?PPRE}]),
{ok, #net_address{address={_,LPort}}} = get_tcp_address(ErtsL),
@@ -193,25 +239,41 @@ setup_proxy(Ip, Port, Parent) ->
Parent ! {self(), Err}
end.
+
+%% we may not always want the nodelay behaviour
+%% %% for performance reasons
+
+nodelay() ->
+ case application:get_env(kernel, dist_nodelay) of
+ undefined ->
+ {nodelay, true};
+ {ok, true} ->
+ {nodelay, true};
+ {ok, false} ->
+ {nodelay, false};
+ _ ->
+ {nodelay, true}
+ end.
+
setup_connection(World, ErtsListen) ->
process_flag(trap_exit, true),
{ok, TcpAddress} = get_tcp_address(ErtsListen),
{_Addr,Port} = TcpAddress#net_address.address,
- {ok, Erts} = gen_tcp:connect({127,0,0,1}, Port, [{active, true}, binary, {packet,?PPRE}]),
- ssl:setopts(World, [{active,true}, {packet,?PPRE}]),
+ {ok, Erts} = gen_tcp:connect({127,0,0,1}, Port, [{active, true}, binary, {packet,?PPRE}, nodelay()]),
+ ssl:setopts(World, [{active,true}, {packet,?PPRE}, nodelay()]),
loop_conn_setup(World, Erts).
loop_conn_setup(World, Erts) ->
receive
{ssl, World, Data = <<$a, _/binary>>} ->
gen_tcp:send(Erts, Data),
- ssl:setopts(World, [{packet,?PPOST}]),
- inet:setopts(Erts, [{packet,?PPOST}]),
+ ssl:setopts(World, [{packet,?PPOST}, nodelay()]),
+ inet:setopts(Erts, [{packet,?PPOST}, nodelay()]),
loop_conn(World, Erts);
{tcp, Erts, Data = <<$a, _/binary>>} ->
ssl:send(World, Data),
- ssl:setopts(World, [{packet,?PPOST}]),
- inet:setopts(Erts, [{packet,?PPOST}]),
+ ssl:setopts(World, [{packet,?PPOST}, nodelay()]),
+ inet:setopts(Erts, [{packet,?PPOST}, nodelay()]),
loop_conn(World, Erts);
{ssl, World, Data = <<_, _/binary>>} ->
gen_tcp:send(Erts, Data),
diff --git a/lib/ssl/src/ssl_v3.erl b/lib/ssl/src/ssl_v3.erl
index 5e043624a7..f169059a75 100644
--- a/lib/ssl/src/ssl_v3.erl
+++ b/lib/ssl/src/ssl_v3.erl
@@ -144,6 +144,7 @@ suites() ->
?TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
?TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
?TLS_RSA_WITH_AES_128_CBC_SHA,
+ ?TLS_DHE_RSA_WITH_DES_CBC_SHA,
?TLS_RSA_WITH_DES_CBC_SHA
].
diff --git a/lib/ssl/src/tls_connection.erl b/lib/ssl/src/tls_connection.erl
index 3093508f61..b2b85eaf8d 100644
--- a/lib/ssl/src/tls_connection.erl
+++ b/lib/ssl/src/tls_connection.erl
@@ -168,9 +168,10 @@ hello(start, #state{host = Host, port = Port, role = client,
Cache, CacheCb, Renegotiation, Cert),
Version = Hello#client_hello.client_version,
+ HelloVersion = tls_record:lowest_protocol_version(SslOpts#ssl_options.versions),
Handshake0 = ssl_handshake:init_handshake_history(),
{BinMsg, ConnectionStates, Handshake} =
- encode_handshake(Hello, Version, ConnectionStates0, Handshake0),
+ encode_handshake(Hello, HelloVersion, ConnectionStates0, Handshake0),
Transport:send(Socket, BinMsg),
State1 = State0#state{connection_states = ConnectionStates,
negotiated_version = Version, %% Requested version
@@ -211,7 +212,7 @@ hello(Hello = #client_hello{client_version = ClientVersion,
client_ecc = {EllipticCurves, EcPointFormats},
negotiated_protocol = Protocol}, ?MODULE)
end;
-hello(Hello,
+hello(Hello = #server_hello{},
#state{connection_states = ConnectionStates0,
negotiated_version = ReqVersion,
role = client,
diff --git a/lib/ssl/src/tls_record.erl b/lib/ssl/src/tls_record.erl
index aa524f0225..9348c8bbdd 100644
--- a/lib/ssl/src/tls_record.erl
+++ b/lib/ssl/src/tls_record.erl
@@ -41,8 +41,9 @@
-export([encode_plain_text/4]).
%% Protocol version handling
--export([protocol_version/1, lowest_protocol_version/2,
- highest_protocol_version/1, is_higher/2, supported_protocol_versions/0,
+-export([protocol_version/1, lowest_protocol_version/1, lowest_protocol_version/2,
+ highest_protocol_version/1, highest_protocol_version/2,
+ is_higher/2, supported_protocol_versions/0,
is_acceptable_version/1, is_acceptable_version/2]).
-export_type([tls_version/0, tls_atom_version/0]).
@@ -257,6 +258,18 @@ lowest_protocol_version(Version = {M,_},
Version;
lowest_protocol_version(_,Version) ->
Version.
+
+%%--------------------------------------------------------------------
+-spec lowest_protocol_version([tls_version()]) -> tls_version().
+%%
+%% Description: Lowest protocol version present in a list
+%%--------------------------------------------------------------------
+lowest_protocol_version([]) ->
+ lowest_protocol_version();
+lowest_protocol_version(Versions) ->
+ [Ver | Vers] = Versions,
+ lowest_list_protocol_version(Ver, Vers).
+
%%--------------------------------------------------------------------
-spec highest_protocol_version([tls_version()]) -> tls_version().
%%
@@ -266,19 +279,29 @@ highest_protocol_version([]) ->
highest_protocol_version();
highest_protocol_version(Versions) ->
[Ver | Vers] = Versions,
- highest_protocol_version(Ver, Vers).
+ highest_list_protocol_version(Ver, Vers).
-highest_protocol_version(Version, []) ->
+%%--------------------------------------------------------------------
+-spec highest_protocol_version(tls_version(), tls_version()) -> tls_version().
+%%
+%% Description: Highest protocol version of two given versions
+%%--------------------------------------------------------------------
+highest_protocol_version(Version = {M, N}, {M, O}) when N > O ->
+ Version;
+highest_protocol_version({M, _},
+ Version = {M, _}) ->
Version;
-highest_protocol_version(Version = {N, M}, [{N, O} | Rest]) when M > O ->
- highest_protocol_version(Version, Rest);
-highest_protocol_version({M, _}, [Version = {M, _} | Rest]) ->
- highest_protocol_version(Version, Rest);
-highest_protocol_version(Version = {M,_}, [{N,_} | Rest]) when M > N ->
- highest_protocol_version(Version, Rest);
-highest_protocol_version(_, [Version | Rest]) ->
- highest_protocol_version(Version, Rest).
+highest_protocol_version(Version = {M,_},
+ {N, _}) when M > N ->
+ Version;
+highest_protocol_version(_,Version) ->
+ Version.
+%%--------------------------------------------------------------------
+-spec is_higher(V1 :: tls_version(), V2::tls_version()) -> boolean().
+%%
+%% Description: Is V1 > V2
+%%--------------------------------------------------------------------
is_higher({M, N}, {M, O}) when N > O ->
true;
is_higher({M, _}, {N, _}) when M > N ->
@@ -352,6 +375,17 @@ is_acceptable_version(_,_) ->
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
+
+lowest_list_protocol_version(Ver, []) ->
+ Ver;
+lowest_list_protocol_version(Ver1, [Ver2 | Rest]) ->
+ lowest_list_protocol_version(lowest_protocol_version(Ver1, Ver2), Rest).
+
+highest_list_protocol_version(Ver, []) ->
+ Ver;
+highest_list_protocol_version(Ver1, [Ver2 | Rest]) ->
+ highest_list_protocol_version(highest_protocol_version(Ver1, Ver2), Rest).
+
encode_tls_cipher_text(Type, {MajVer, MinVer}, Fragment) ->
Length = erlang:iolist_size(Fragment),
[<<?BYTE(Type), ?BYTE(MajVer), ?BYTE(MinVer), ?UINT16(Length)>>, Fragment].
@@ -370,6 +404,10 @@ mac_hash({3, N} = Version, MacAlg, MacSecret, SeqNo, Type, Length, Fragment)
highest_protocol_version() ->
highest_protocol_version(supported_protocol_versions()).
+lowest_protocol_version() ->
+ lowest_protocol_version(supported_protocol_versions()).
+
+
sufficient_tlsv1_2_crypto_support() ->
CryptoSupport = crypto:supports(),
proplists:get_bool(sha256, proplists:get_value(hashs, CryptoSupport)).
diff --git a/lib/ssl/test/ssl_ECC_SUITE.erl b/lib/ssl/test/ssl_ECC_SUITE.erl
index 3a9f21ea99..75b639b23b 100644
--- a/lib/ssl/test/ssl_ECC_SUITE.erl
+++ b/lib/ssl/test/ssl_ECC_SUITE.erl
@@ -248,10 +248,13 @@ start_client(openssl, Port, CA, OwnCa, Cert, Key, Config) ->
PrivDir = ?config(priv_dir, Config),
NewCA = new_ca(filename:join(PrivDir, "new_ca.pem"), CA, OwnCa),
Version = tls_record:protocol_version(tls_record:highest_protocol_version([])),
- Cmd = "openssl s_client -verify 2 -port " ++ integer_to_list(Port) ++ ssl_test_lib:version_flag(Version) ++
- " -cert " ++ Cert ++ " -CAfile " ++ NewCA
- ++ " -key " ++ Key ++ " -host localhost -msg -debug",
- OpenSslPort = open_port({spawn, Cmd}, [stderr_to_stdout]),
+ Exe = "openssl",
+ Args = ["s_client", "-verify", "2", "-port", integer_to_list(Port),
+ ssl_test_lib:version_flag(Version),
+ "-cert", Cert, "-CAfile", NewCA,
+ "-key", Key, "-host","localhost", "-msg", "-debug"],
+
+ OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args),
true = port_command(OpenSslPort, "Hello world"),
OpenSslPort;
start_client(erlang, Port, CA, _, Cert, Key, Config) ->
@@ -270,10 +273,11 @@ start_server(openssl, CA, OwnCa, Cert, Key, Config) ->
Port = ssl_test_lib:inet_port(node()),
Version = tls_record:protocol_version(tls_record:highest_protocol_version([])),
- Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++ ssl_test_lib:version_flag(Version) ++
- " -verify 2 -cert " ++ Cert ++ " -CAfile " ++ NewCA
- ++ " -key " ++ Key ++ " -msg -debug",
- OpenSslPort = open_port({spawn, Cmd}, [stderr_to_stdout]),
+ Exe = "openssl",
+ Args = ["s_server", "-accept", integer_to_list(Port), ssl_test_lib:version_flag(Version),
+ "-verify", "2", "-cert", Cert, "-CAfile", NewCA,
+ "-key", Key, "-msg", "-debug"],
+ OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args),
true = port_command(OpenSslPort, "Hello world"),
{OpenSslPort, Port};
start_server(erlang, CA, _, Cert, Key, Config) ->
diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl
index 6f6107de2c..05b040a2ab 100644
--- a/lib/ssl/test/ssl_basic_SUITE.erl
+++ b/lib/ssl/test/ssl_basic_SUITE.erl
@@ -35,7 +35,6 @@
-include("tls_record.hrl").
-include("tls_handshake.hrl").
--define('24H_in_sec', 86400).
-define(TIMEOUT, 20000).
-define(EXPIRE, 10).
-define(SLEEP, 500).
@@ -96,6 +95,7 @@ options_tests() ->
[der_input,
misc_ssl_options,
ssl_options_not_proplist,
+ raw_ssl_option,
socket_options,
invalid_inet_get_option,
invalid_inet_get_option_not_list,
@@ -136,6 +136,7 @@ api_tests() ->
shutdown_both,
shutdown_error,
hibernate,
+ hibernate_right_away,
listen_socket,
ssl_accept_timeout,
ssl_recv_timeout,
@@ -331,6 +332,14 @@ init_per_testcase(clear_pem_cache, Config) ->
ct:log("TLS/SSL version ~p~n ", [tls_record:supported_protocol_versions()]),
ct:timetrap({seconds, 20}),
Config;
+init_per_testcase(raw_ssl_option, Config) ->
+ ct:timetrap({seconds, 5}),
+ case os:type() of
+ {unix,linux} ->
+ Config;
+ _ ->
+ {skip, "Raw options are platform-specific"}
+ end;
init_per_testcase(_TestCase, Config) ->
ct:log("TLS/SSL version ~p~n ", [tls_record:supported_protocol_versions()]),
@@ -1156,6 +1165,23 @@ ssl_options_not_proplist(Config) when is_list(Config) ->
BadOption]).
%%--------------------------------------------------------------------
+raw_ssl_option() ->
+ [{doc,"Ensure that a single 'raw' option is passed to ssl:listen correctly."}].
+
+raw_ssl_option(Config) when is_list(Config) ->
+ % 'raw' option values are platform-specific; these are the Linux values:
+ IpProtoTcp = 6,
+ % Use TCP_KEEPIDLE, because (e.g.) TCP_MAXSEG can't be read back reliably.
+ TcpKeepIdle = 4,
+ KeepAliveTimeSecs = 55,
+ LOptions = [{raw, IpProtoTcp, TcpKeepIdle, <<KeepAliveTimeSecs:32/native>>}],
+ {ok, LSocket} = ssl:listen(0, LOptions),
+ % Per http://www.erlang.org/doc/man/inet.html#getopts-2, we have to specify
+ % exactly which raw option we want, and the size of the buffer.
+ {ok, [{raw, IpProtoTcp, TcpKeepIdle, <<KeepAliveTimeSecs:32/native>>}]} = ssl:getopts(LSocket, [{raw, IpProtoTcp, TcpKeepIdle, 4}]).
+
+
+%%--------------------------------------------------------------------
versions() ->
[{doc,"Test API function versions/0"}].
@@ -2898,6 +2924,43 @@ hibernate(Config) ->
ssl_test_lib:close(Client).
%%--------------------------------------------------------------------
+
+hibernate_right_away() ->
+ [{doc,"Check that an SSL connection that is configured to hibernate "
+ "after 0 or 1 milliseconds hibernates as soon as possible and not "
+ "crashes"}].
+
+hibernate_right_away(Config) ->
+ ClientOpts = ?config(client_opts, Config),
+ ServerOpts = ?config(server_opts, Config),
+
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ StartServerOpts = [{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {ssl_test_lib, send_recv_result_active, []}},
+ {options, ServerOpts}],
+ StartClientOpts = [return_socket,
+ {node, ClientNode},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib, send_recv_result_active, []}}],
+
+ Server1 = ssl_test_lib:start_server(StartServerOpts),
+ Port1 = ssl_test_lib:inet_port(Server1),
+ {Client1, #sslsocket{}} = ssl_test_lib:start_client(StartClientOpts ++
+ [{port, Port1}, {options, [{hibernate_after, 0}|ClientOpts]}]),
+ ssl_test_lib:close(Server1),
+ ssl_test_lib:close(Client1),
+
+ Server2 = ssl_test_lib:start_server(StartServerOpts),
+ Port2 = ssl_test_lib:inet_port(Server2),
+ {Client2, #sslsocket{}} = ssl_test_lib:start_client(StartClientOpts ++
+ [{port, Port2}, {options, [{hibernate_after, 1}|ClientOpts]}]),
+ ssl_test_lib:close(Server2),
+ ssl_test_lib:close(Client2).
+
+%%--------------------------------------------------------------------
listen_socket() ->
[{doc,"Check error handling and inet compliance when calling API functions with listen sockets."}].
diff --git a/lib/ssl/test/ssl_dist_SUITE.erl b/lib/ssl/test/ssl_dist_SUITE.erl
index 72d62b29a7..092015d3d8 100644
--- a/lib/ssl/test/ssl_dist_SUITE.erl
+++ b/lib/ssl/test/ssl_dist_SUITE.erl
@@ -40,7 +40,8 @@
%% Common Test interface functions -----------------------------------
%%--------------------------------------------------------------------
all() ->
- [basic, payload, plain_options, plain_verify_options].
+ [basic, payload, plain_options, plain_verify_options, nodelay_option,
+ listen_port_options, listen_options, use_interface].
groups() ->
[].
@@ -250,6 +251,146 @@ plain_verify_options(Config) when is_list(Config) ->
stop_ssl_node(NH1),
stop_ssl_node(NH2),
success(Config).
+%%--------------------------------------------------------------------
+nodelay_option() ->
+ [{doc,"Test specifying dist_nodelay option"}].
+nodelay_option(Config) ->
+ try
+ %% The default is 'true', so try setting it to 'false'.
+ application:set_env(kernel, dist_nodelay, false),
+ basic(Config)
+ after
+ application:unset_env(kernel, dist_nodelay)
+ end.
+
+listen_port_options() ->
+ [{doc, "Test specifying listening ports"}].
+listen_port_options(Config) when is_list(Config) ->
+ %% Start a node, and get the port number it's listening on.
+ NH1 = start_ssl_node(Config),
+ Node1 = NH1#node_handle.nodename,
+ Name1 = lists:takewhile(fun(C) -> C =/= $@ end, atom_to_list(Node1)),
+ {ok, NodesPorts} = apply_on_ssl_node(NH1, fun net_adm:names/0),
+ {Name1, Port1} = lists:keyfind(Name1, 1, NodesPorts),
+
+ %% Now start a second node, configuring it to use the same port
+ %% number.
+ PortOpt1 = "-kernel inet_dist_listen_min " ++ integer_to_list(Port1) ++
+ " inet_dist_listen_max " ++ integer_to_list(Port1),
+
+ try start_ssl_node([{additional_dist_opts, PortOpt1} | Config]) of
+ #node_handle{} ->
+ %% If the node was able to start, it didn't take the port
+ %% option into account.
+ exit(unexpected_success)
+ catch
+ exit:{accept_failed, timeout} ->
+ %% The node failed to start, as expected.
+ ok
+ end,
+
+ %% Try again, now specifying a high max port.
+ PortOpt2 = "-kernel inet_dist_listen_min " ++ integer_to_list(Port1) ++
+ " inet_dist_listen_max 65535",
+ NH2 = start_ssl_node([{additional_dist_opts, PortOpt2} | Config]),
+ Node2 = NH2#node_handle.nodename,
+ Name2 = lists:takewhile(fun(C) -> C =/= $@ end, atom_to_list(Node2)),
+ {ok, NodesPorts2} = apply_on_ssl_node(NH2, fun net_adm:names/0),
+ {Name2, Port2} = lists:keyfind(Name2, 1, NodesPorts2),
+
+ %% The new port should be higher:
+ if Port2 > Port1 ->
+ ok;
+ true ->
+ error({port, Port2, not_higher_than, Port1})
+ end,
+
+ stop_ssl_node(NH1),
+ stop_ssl_node(NH2),
+ success(Config).
+%%--------------------------------------------------------------------
+listen_options() ->
+ [{doc, "Test inet_dist_listen_options"}].
+listen_options(Config) when is_list(Config) ->
+ Prio = 1,
+ case gen_udp:open(0, [{priority,Prio}]) of
+ {ok,Socket} ->
+ case inet:getopts(Socket, [priority]) of
+ {ok,[{priority,Prio}]} ->
+ ok = gen_udp:close(Socket),
+ do_listen_options(Prio, Config);
+ _ ->
+ ok = gen_udp:close(Socket),
+ {skip,
+ "Can not set priority "++integer_to_list(Prio)++
+ " on socket"}
+ end;
+ {error,_} ->
+ {skip, "Can not set priority on socket"}
+ end.
+
+do_listen_options(Prio, Config) ->
+ PriorityString0 = "[{priority,"++integer_to_list(Prio)++"}]",
+ PriorityString =
+ case os:cmd("echo [{a,1}]") of
+ "[{a,1}]"++_ ->
+ PriorityString0;
+ _ ->
+ %% Some shells need quoting of [{}]
+ "'"++PriorityString0++"'"
+ end,
+
+ Options = "-kernel inet_dist_listen_options " ++ PriorityString,
+
+ NH1 = start_ssl_node([{additional_dist_opts, Options} | Config]),
+ NH2 = start_ssl_node([{additional_dist_opts, Options} | Config]),
+ Node2 = NH2#node_handle.nodename,
+
+ pong = apply_on_ssl_node(NH1, fun () -> net_adm:ping(Node2) end),
+
+ PrioritiesNode1 =
+ apply_on_ssl_node(NH1, fun get_socket_priorities/0),
+ PrioritiesNode2 =
+ apply_on_ssl_node(NH2, fun get_socket_priorities/0),
+
+ Elevated1 = [P || P <- PrioritiesNode1, P =:= Prio],
+ ?t:format("Elevated1: ~p~n", [Elevated1]),
+ Elevated2 = [P || P <- PrioritiesNode2, P =:= Prio],
+ ?t:format("Elevated2: ~p~n", [Elevated2]),
+ [_|_] = Elevated1,
+ [_|_] = Elevated2,
+
+ stop_ssl_node(NH1),
+ stop_ssl_node(NH2),
+ success(Config).
+%%--------------------------------------------------------------------
+use_interface() ->
+ [{doc, "Test inet_dist_use_interface"}].
+use_interface(Config) when is_list(Config) ->
+ %% Force the node to listen only on the loopback interface.
+ IpString = "'{127,0,0,1}'",
+ Options = "-kernel inet_dist_use_interface " ++ IpString,
+
+ %% Start a node, and get the port number it's listening on.
+ NH1 = start_ssl_node([{additional_dist_opts, Options} | Config]),
+ Node1 = NH1#node_handle.nodename,
+ Name = lists:takewhile(fun(C) -> C =/= $@ end, atom_to_list(Node1)),
+ {ok, NodesPorts} = apply_on_ssl_node(NH1, fun net_adm:names/0),
+ {Name, Port} = lists:keyfind(Name, 1, NodesPorts),
+
+ %% Now find the socket listening on that port, and check its sockname.
+ Sockets = apply_on_ssl_node(
+ NH1,
+ fun() ->
+ [inet:sockname(P) ||
+ P <- erlang:ports(),
+ {ok, Port} =:= (catch inet:port(P))]
+ end),
+ %% And check that it's actually listening on localhost.
+ [{ok,{{127,0,0,1},Port}}] = Sockets,
+
+ stop_ssl_node(NH1),
+ success(Config).
%%--------------------------------------------------------------------
%%% Internal functions -----------------------------------------------
@@ -264,6 +405,12 @@ tstsrvr_format(Fmt, ArgList) ->
send_to_tstcntrl(Message) ->
send_to_tstsrvr({message, Message}).
+get_socket_priorities() ->
+ [Priority ||
+ {ok,[{priority,Priority}]} <-
+ [inet:getopts(Port, [priority]) ||
+ Port <- erlang:ports(),
+ element(2, erlang:port_info(Port, name)) =:= "tcp_inet"]].
%%
%% test_server side api
diff --git a/lib/ssl/test/ssl_session_cache_SUITE.erl b/lib/ssl/test/ssl_session_cache_SUITE.erl
index 924898f6fa..85345c814f 100644
--- a/lib/ssl/test/ssl_session_cache_SUITE.erl
+++ b/lib/ssl/test/ssl_session_cache_SUITE.erl
@@ -31,6 +31,7 @@
-define(SLEEP, 500).
-define(TIMEOUT, 60000).
-define(LONG_TIMEOUT, 600000).
+-define(MAX_TABLE_SIZE, 5).
-behaviour(ssl_session_cache_api).
@@ -46,7 +47,9 @@ all() ->
[session_cleanup,
session_cache_process_list,
session_cache_process_mnesia,
- client_unique_session].
+ client_unique_session,
+ max_table_size
+ ].
groups() ->
[].
@@ -92,7 +95,17 @@ init_per_testcase(session_cleanup, Config) ->
Config;
init_per_testcase(client_unique_session, Config) ->
- ct:timetrap({seconds, 20}),
+ ct:timetrap({seconds, 40}),
+ Config;
+
+init_per_testcase(max_table_size, Config) ->
+ ssl:stop(),
+ application:load(ssl),
+ application:set_env(ssl, session_cache_server_max, ?MAX_TABLE_SIZE),
+ application:set_env(ssl, session_cache_client_max, ?MAX_TABLE_SIZE),
+ application:set_env(ssl, session_delay_cleanup_time, ?DELAY),
+ ssl:start(),
+ ct:timetrap({seconds, 40}),
Config.
init_customized_session_cache(Type, Config) ->
@@ -122,6 +135,10 @@ end_per_testcase(session_cleanup, Config) ->
application:unset_env(ssl, session_delay_cleanup_time),
application:unset_env(ssl, session_lifetime),
end_per_testcase(default_action, Config);
+end_per_testcase(max_table_size, Config) ->
+ application:unset_env(ssl, session_cach_server_max),
+ application:unset_env(ssl, session_cach_client_max),
+ end_per_testcase(default_action, Config);
end_per_testcase(Case, Config) when Case == session_cache_process_list;
Case == session_cache_process_mnesia ->
ets:delete(ssl_test),
@@ -148,7 +165,7 @@ client_unique_session(Config) when is_list(Config) ->
{options, ServerOpts}]),
Port = ssl_test_lib:inet_port(Server),
LastClient = clients_start(Server,
- ClientNode, Hostname, Port, ClientOpts, 20),
+ ClientNode, Hostname, Port, ClientOpts, client_unique_session, 20),
receive
{LastClient, {ok, _}} ->
ok
@@ -157,7 +174,8 @@ client_unique_session(Config) when is_list(Config) ->
[_, _,_, _, Prop] = StatusInfo,
State = ssl_test_lib:state(Prop),
ClientCache = element(2, State),
- 1 = ets:info(ClientCache, size),
+
+ 1 = ssl_session_cache:size(ClientCache),
ssl_test_lib:close(Server, 500),
ssl_test_lib:close(LastClient).
@@ -223,35 +241,7 @@ session_cleanup(Config) when is_list(Config) ->
ssl_test_lib:close(Server),
ssl_test_lib:close(Client).
-check_timer(Timer) ->
- case erlang:read_timer(Timer) of
- false ->
- {status, _, _, _} = sys:get_status(whereis(ssl_manager)),
- timer:sleep(?SLEEP),
- {status, _, _, _} = sys:get_status(whereis(ssl_manager)),
- ok;
- Int ->
- ct:sleep(Int),
- check_timer(Timer)
- end.
-get_delay_timers() ->
- {status, _, _, StatusInfo} = sys:get_status(whereis(ssl_manager)),
- [_, _,_, _, Prop] = StatusInfo,
- State = ssl_test_lib:state(Prop),
- case element(8, State) of
- {undefined, undefined} ->
- ct:sleep(?SLEEP),
- get_delay_timers();
- {undefined, _} ->
- ct:sleep(?SLEEP),
- get_delay_timers();
- {_, undefined} ->
- ct:sleep(?SLEEP),
- get_delay_timers();
- DelayTimers ->
- DelayTimers
- end.
%%--------------------------------------------------------------------
session_cache_process_list() ->
[{doc,"Test reuse of sessions (short handshake)"}].
@@ -264,6 +254,42 @@ session_cache_process_mnesia(Config) when is_list(Config) ->
session_cache_process(mnesia,Config).
%%--------------------------------------------------------------------
+
+max_table_size() ->
+ [{doc,"Test max limit on session table"}].
+max_table_size(Config) when is_list(Config) ->
+ process_flag(trap_exit, true),
+ ClientOpts = ?config(client_verification_opts, Config),
+ ServerOpts = ?config(server_verification_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ Server =
+ ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {ssl_test_lib, no_result, []}},
+ {tcp_options, [{active, false}]},
+ {options, ServerOpts}]),
+ Port = ssl_test_lib:inet_port(Server),
+ LastClient = clients_start(Server,
+ ClientNode, Hostname, Port, ClientOpts, max_table_size, 20),
+ receive
+ {LastClient, {ok, _}} ->
+ ok
+ end,
+ ct:sleep(1000),
+ {status, _, _, StatusInfo} = sys:get_status(whereis(ssl_manager)),
+ [_, _,_, _, Prop] = StatusInfo,
+ State = ssl_test_lib:state(Prop),
+ ClientCache = element(2, State),
+ ServerCache = element(3, State),
+ N = ssl_session_cache:size(ServerCache),
+ M = ssl_session_cache:size(ClientCache),
+ ct:pal("~p",[{N, M}]),
+ ssl_test_lib:close(Server, 500),
+ ssl_test_lib:close(LastClient),
+ true = N =< ?MAX_TABLE_SIZE,
+ true = M =< ?MAX_TABLE_SIZE.
+
+%%--------------------------------------------------------------------
%%% Session cache API callbacks
%%--------------------------------------------------------------------
@@ -403,21 +429,73 @@ session_cache_process(_Type,Config) when is_list(Config) ->
ssl_basic_SUITE:reuse_session(Config).
-clients_start(_Server, ClientNode, Hostname, Port, ClientOpts, 0) ->
+clients_start(_Server, ClientNode, Hostname, Port, ClientOpts, Test, 0) ->
%% Make sure session is registered
ct:sleep(?SLEEP * 2),
ssl_test_lib:start_client([{node, ClientNode},
{port, Port}, {host, Hostname},
{mfa, {?MODULE, connection_info_result, []}},
- {from, self()}, {options, ClientOpts}]);
-clients_start(Server, ClientNode, Hostname, Port, ClientOpts, N) ->
+ {from, self()}, {options, test_copts(Test, 0, ClientOpts)}]);
+clients_start(Server, ClientNode, Hostname, Port, ClientOpts, Test, N) ->
spawn_link(ssl_test_lib, start_client,
[[{node, ClientNode},
{port, Port}, {host, Hostname},
{mfa, {ssl_test_lib, no_result, []}},
- {from, self()}, {options, ClientOpts}]]),
+ {from, self()}, {options, test_copts(Test, N, ClientOpts)}]]),
Server ! listen,
- clients_start(Server, ClientNode, Hostname, Port, ClientOpts, N-1).
+ wait_for_server(),
+ clients_start(Server, ClientNode, Hostname, Port, ClientOpts, Test, N-1).
connection_info_result(Socket) ->
ssl:connection_information(Socket, [protocol, cipher_suite]).
+
+check_timer(Timer) ->
+ case erlang:read_timer(Timer) of
+ false ->
+ {status, _, _, _} = sys:get_status(whereis(ssl_manager)),
+ timer:sleep(?SLEEP),
+ {status, _, _, _} = sys:get_status(whereis(ssl_manager)),
+ ok;
+ Int ->
+ ct:sleep(Int),
+ check_timer(Timer)
+ end.
+
+get_delay_timers() ->
+ {status, _, _, StatusInfo} = sys:get_status(whereis(ssl_manager)),
+ [_, _,_, _, Prop] = StatusInfo,
+ State = ssl_test_lib:state(Prop),
+ case element(8, State) of
+ {undefined, undefined} ->
+ ct:sleep(?SLEEP),
+ get_delay_timers();
+ {undefined, _} ->
+ ct:sleep(?SLEEP),
+ get_delay_timers();
+ {_, undefined} ->
+ ct:sleep(?SLEEP),
+ get_delay_timers();
+ DelayTimers ->
+ DelayTimers
+ end.
+
+wait_for_server() ->
+ ct:sleep(100).
+
+
+test_copts(_, 0, ClientOpts) ->
+ ClientOpts;
+test_copts(max_table_size, N, ClientOpts) ->
+ Version = tls_record:highest_protocol_version([]),
+ CipherSuites = %%lists:map(fun(X) -> ssl_cipher:suite_definition(X) end, ssl_cipher:filter_suites(ssl_cipher:suites(Version))),
+[ Y|| Y = {Alg,_, _, _} <- lists:map(fun(X) -> ssl_cipher:suite_definition(X) end, ssl_cipher:filter_suites(ssl_cipher:suites(Version))), Alg =/= ecdhe_ecdsa, Alg =/= ecdh_ecdsa, Alg =/= ecdh_rsa, Alg =/= ecdhe_rsa, Alg =/= dhe_dss, Alg =/= dss],
+ case length(CipherSuites) of
+ M when M >= N ->
+ Cipher = lists:nth(N, CipherSuites),
+ ct:pal("~p",[Cipher]),
+ [{ciphers, [Cipher]} | ClientOpts];
+ _ ->
+ ClientOpts
+ end;
+test_copts(_, _, ClientOpts) ->
+ ClientOpts.
diff --git a/lib/ssl/test/ssl_test_lib.erl b/lib/ssl/test/ssl_test_lib.erl
index f25f6f9425..9a76d603b1 100644
--- a/lib/ssl/test/ssl_test_lib.erl
+++ b/lib/ssl/test/ssl_test_lib.erl
@@ -1192,13 +1192,13 @@ wait_for_openssl_server(Port, N) ->
end.
version_flag(tlsv1) ->
- " -tls1 ";
+ "-tls1";
version_flag('tlsv1.1') ->
- " -tls1_1 ";
+ "-tls1_1";
version_flag('tlsv1.2') ->
- " -tls1_2 ";
+ "-tls1_2";
version_flag(sslv3) ->
- " -ssl3 ".
+ "-ssl3".
filter_suites(Ciphers0) ->
Version = tls_record:highest_protocol_version([]),
@@ -1243,3 +1243,9 @@ close_loop(Port, Time, SentClose) ->
ct:log("Timeout~n",[])
end
end.
+
+portable_open_port(Exe, Args) ->
+ AbsPath = os:find_executable(Exe),
+ ct:pal("open_port({spawn_executable, ~p}, [{args, ~p}, stderr_to_stdout]).", [AbsPath, Args]),
+ open_port({spawn_executable, AbsPath},
+ [{args, Args}, stderr_to_stdout]).
diff --git a/lib/ssl/test/ssl_to_openssl_SUITE.erl b/lib/ssl/test/ssl_to_openssl_SUITE.erl
index 16b6cb10b9..119baf1072 100644
--- a/lib/ssl/test/ssl_to_openssl_SUITE.erl
+++ b/lib/ssl/test/ssl_to_openssl_SUITE.erl
@@ -262,12 +262,11 @@ basic_erlang_client_openssl_server(Config) when is_list(Config) ->
CertFile = proplists:get_value(certfile, ServerOpts),
KeyFile = proplists:get_value(keyfile, ServerOpts),
- Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++
- " -cert " ++ CertFile ++ " -key " ++ KeyFile,
-
- ct:log("openssl cmd: ~p~n", [Cmd]),
+ Exe = "openssl",
+ Args = ["s_server", "-accept", integer_to_list(Port),
+ "-cert", CertFile, "-key", KeyFile],
- OpensslPort = open_port({spawn, Cmd}, [stderr_to_stdout]),
+ OpensslPort = ssl_test_lib:portable_open_port(Exe, Args),
ssl_test_lib:wait_for_openssl_server(Port),
@@ -302,13 +301,11 @@ basic_erlang_server_openssl_client(Config) when is_list(Config) ->
{mfa, {?MODULE, erlang_ssl_receive, [Data]}},
{options, ServerOpts}]),
Port = ssl_test_lib:inet_port(Server),
-
- Cmd = "openssl s_client -port " ++ integer_to_list(Port) ++
- " -host localhost" ++ workaround_openssl_s_clinent(),
-
- ct:log("openssl cmd: ~p~n", [Cmd]),
- OpenSslPort = open_port({spawn, Cmd}, [stderr_to_stdout]),
+ Exe = "openssl",
+ Args = ["s_client", "-connect", "localhost:" ++ integer_to_list(Port) | workaround_openssl_s_clinent()],
+
+ OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args),
true = port_command(OpenSslPort, Data),
ssl_test_lib:check_result(Server, ok),
@@ -334,12 +331,12 @@ erlang_client_openssl_server(Config) when is_list(Config) ->
CertFile = proplists:get_value(certfile, ServerOpts),
KeyFile = proplists:get_value(keyfile, ServerOpts),
Version = tls_record:protocol_version(tls_record:highest_protocol_version([])),
- Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++ ssl_test_lib:version_flag(Version) ++
- " -cert " ++ CertFile ++ " -key " ++ KeyFile,
-
- ct:log("openssl cmd: ~p~n", [Cmd]),
-
- OpensslPort = open_port({spawn, Cmd}, [stderr_to_stdout]),
+ Exe = "openssl",
+ Args = ["s_server", "-accept", integer_to_list(Port),
+ ssl_test_lib:version_flag(Version),
+ "-cert", CertFile, "-key", KeyFile],
+
+ OpensslPort = ssl_test_lib:portable_open_port(Exe, Args),
ssl_test_lib:wait_for_openssl_server(Port),
@@ -376,12 +373,12 @@ erlang_server_openssl_client(Config) when is_list(Config) ->
Port = ssl_test_lib:inet_port(Server),
Version = tls_record:protocol_version(tls_record:highest_protocol_version([])),
- Cmd = "openssl s_client -port " ++ integer_to_list(Port) ++ ssl_test_lib:version_flag(Version) ++
- " -host localhost",
+ Exe = "openssl",
+ Args = ["s_client", "-connect", "localhost: " ++ integer_to_list(Port),
+ ssl_test_lib:version_flag(Version)],
- ct:log("openssl cmd: ~p~n", [Cmd]),
+ OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args),
- OpenSslPort = open_port({spawn, Cmd}, [stderr_to_stdout]),
true = port_command(OpenSslPort, Data),
ssl_test_lib:check_result(Server, ok),
@@ -407,14 +404,13 @@ erlang_client_openssl_server_dsa_cert(Config) when is_list(Config) ->
CertFile = proplists:get_value(certfile, ServerOpts),
KeyFile = proplists:get_value(keyfile, ServerOpts),
Version = tls_record:protocol_version(tls_record:highest_protocol_version([])),
+ Exe = "openssl",
+ Args = ["s_server", "-accept", integer_to_list(Port),
+ ssl_test_lib:version_flag(Version),
+ "-cert", CertFile, "-CAfile", CaCertFile,
+ "-key", KeyFile, "-Verify", "2", "-msg"],
- Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++ ssl_test_lib:version_flag(Version) ++
- " -cert " ++ CertFile ++ " -CAfile " ++ CaCertFile
- ++ " -key " ++ KeyFile ++ " -Verify 2 -msg",
-
- ct:log("openssl cmd: ~p~n", [Cmd]),
-
- OpensslPort = open_port({spawn, Cmd}, [stderr_to_stdout]),
+ OpensslPort = ssl_test_lib:portable_open_port(Exe, Args),
ssl_test_lib:wait_for_openssl_server(Port),
@@ -455,13 +451,14 @@ erlang_server_openssl_client_dsa_cert(Config) when is_list(Config) ->
{options, ServerOpts}]),
Port = ssl_test_lib:inet_port(Server),
Version = tls_record:protocol_version(tls_record:highest_protocol_version([])),
- Cmd = "openssl s_client -port " ++ integer_to_list(Port) ++ ssl_test_lib:version_flag(Version) ++
- " -host localhost " ++ " -cert " ++ CertFile ++ " -CAfile " ++ CaCertFile
- ++ " -key " ++ KeyFile ++ " -msg",
-
- ct:log("openssl cmd: ~p~n", [Cmd]),
-
- OpenSslPort = open_port({spawn, Cmd}, [stderr_to_stdout]),
+ Exe = "openssl",
+ Args = ["s_client", "-connect", "localhost: " ++ integer_to_list(Port),
+ ssl_test_lib:version_flag(Version),
+ "-cert", CertFile,
+ "-CAfile", CaCertFile,
+ "-key", KeyFile, "-msg"],
+
+ OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args),
true = port_command(OpenSslPort, Data),
ssl_test_lib:check_result(Server, ok),
@@ -491,12 +488,13 @@ erlang_server_openssl_client_reuse_session(Config) when is_list(Config) ->
{options, ServerOpts}]),
Port = ssl_test_lib:inet_port(Server),
Version = tls_record:protocol_version(tls_record:highest_protocol_version([])),
- Cmd = "openssl s_client -port " ++ integer_to_list(Port) ++ ssl_test_lib:version_flag(Version) ++
- " -host localhost -reconnect",
-
- ct:log("openssl cmd: ~p~n", [Cmd]),
- OpenSslPort = open_port({spawn, Cmd}, [stderr_to_stdout]),
+ Exe = "openssl",
+ Args = ["s_client", "-connect", "localhost:" ++ integer_to_list(Port),
+ ssl_test_lib:version_flag(Version),
+ "-reconnect"],
+
+ OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args),
true = port_command(OpenSslPort, Data),
@@ -527,12 +525,12 @@ erlang_client_openssl_server_renegotiate(Config) when is_list(Config) ->
KeyFile = proplists:get_value(keyfile, ServerOpts),
Version = tls_record:protocol_version(tls_record:highest_protocol_version([])),
- Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++ ssl_test_lib:version_flag(Version) ++
- " -cert " ++ CertFile ++ " -key " ++ KeyFile ++ " -msg",
+ Exe = "openssl",
+ Args = ["s_server", "-accept", integer_to_list(Port),
+ ssl_test_lib:version_flag(Version),
+ "-cert", CertFile, "-key", KeyFile, "-msg"],
- ct:log("openssl cmd: ~p~n", [Cmd]),
-
- OpensslPort = open_port({spawn, Cmd}, [stderr_to_stdout]),
+ OpensslPort = ssl_test_lib:portable_open_port(Exe, Args),
ssl_test_lib:wait_for_openssl_server(Port),
@@ -576,12 +574,12 @@ erlang_client_openssl_server_nowrap_seqnum(Config) when is_list(Config) ->
CertFile = proplists:get_value(certfile, ServerOpts),
KeyFile = proplists:get_value(keyfile, ServerOpts),
Version = tls_record:protocol_version(tls_record:highest_protocol_version([])),
- Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++ ssl_test_lib:version_flag(Version) ++
- " -cert " ++ CertFile ++ " -key " ++ KeyFile ++ " -msg",
+ Exe = "openssl",
+ Args = ["s_server", "-accept", integer_to_list(Port),
+ ssl_test_lib:version_flag(Version),
+ "-cert", CertFile, "-key", KeyFile, "-msg"],
- ct:log("openssl cmd: ~p~n", [Cmd]),
-
- OpensslPort = open_port({spawn, Cmd}, [stderr_to_stdout]),
+ OpensslPort = ssl_test_lib:portable_open_port(Exe, Args),
ssl_test_lib:wait_for_openssl_server(Port),
@@ -622,12 +620,12 @@ erlang_server_openssl_client_nowrap_seqnum(Config) when is_list(Config) ->
{options, [{renegotiate_at, N}, {reuse_sessions, false} | ServerOpts]}]),
Port = ssl_test_lib:inet_port(Server),
Version = tls_record:protocol_version(tls_record:highest_protocol_version([])),
- Cmd = "openssl s_client -port " ++ integer_to_list(Port) ++ ssl_test_lib:version_flag(Version) ++
- " -host localhost -msg",
-
- ct:log("openssl cmd: ~p~n", [Cmd]),
+ Exe = "openssl",
+ Args = ["s_client","-connect", "localhost: " ++ integer_to_list(Port),
+ ssl_test_lib:version_flag(Version),
+ "-msg"],
- OpenSslPort = open_port({spawn, Cmd}, [stderr_to_stdout]),
+ OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args),
true = port_command(OpenSslPort, Data),
@@ -657,13 +655,13 @@ erlang_client_openssl_server_no_server_ca_cert(Config) when is_list(Config) ->
CertFile = proplists:get_value(certfile, ServerOpts),
KeyFile = proplists:get_value(keyfile, ServerOpts),
Version = tls_record:protocol_version(tls_record:highest_protocol_version([])),
- Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++ ssl_test_lib:version_flag(Version) ++
- " -cert " ++ CertFile ++ " -key " ++ KeyFile ++ " -msg",
+ Exe = "openssl",
+ Args = ["s_server", "-accept", integer_to_list(Port),
+ ssl_test_lib:version_flag(Version),
+ "-cert", CertFile, "-key", KeyFile, "-msg"],
- ct:log("openssl cmd: ~p~n", [Cmd]),
-
- OpensslPort = open_port({spawn, Cmd}, [stderr_to_stdout]),
-
+ OpensslPort = ssl_test_lib:portable_open_port(Exe, Args),
+
ssl_test_lib:wait_for_openssl_server(Port),
Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
@@ -699,13 +697,13 @@ erlang_client_openssl_server_client_cert(Config) when is_list(Config) ->
CaCertFile = proplists:get_value(cacertfile, ServerOpts),
KeyFile = proplists:get_value(keyfile, ServerOpts),
Version = tls_record:protocol_version(tls_record:highest_protocol_version([])),
- Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++ ssl_test_lib:version_flag(Version) ++
- " -cert " ++ CertFile ++ " -CAfile " ++ CaCertFile
- ++ " -key " ++ KeyFile ++ " -Verify 2",
+ Exe = "openssl",
+ Args = ["s_server", "-accept", integer_to_list(Port),
+ ssl_test_lib:version_flag(Version),
+ "-cert", CertFile, "-CAfile", CaCertFile,
+ "-key", KeyFile, "-Verify", "2"],
- ct:log("openssl cmd: ~p~n", [Cmd]),
-
- OpensslPort = open_port({spawn, Cmd}, [stderr_to_stdout]),
+ OpensslPort = ssl_test_lib:portable_open_port(Exe, Args),
ssl_test_lib:wait_for_openssl_server(Port),
@@ -750,13 +748,14 @@ erlang_server_openssl_client_client_cert(Config) when is_list(Config) ->
CertFile = proplists:get_value(certfile, ClientOpts),
KeyFile = proplists:get_value(keyfile, ClientOpts),
Version = tls_record:protocol_version(tls_record:highest_protocol_version([])),
- Cmd = "openssl s_client -cert " ++ CertFile ++ " -CAfile " ++ CaCertFile
- ++ " -key " ++ KeyFile ++ " -port " ++ integer_to_list(Port) ++ ssl_test_lib:version_flag(Version) ++
- " -host localhost",
-
- ct:log("openssl cmd: ~p~n", [Cmd]),
+ Exe = "openssl",
+ Args = ["s_client", "-cert", CertFile,
+ "-CAfile", CaCertFile,
+ "-key", KeyFile,"-connect", "localhost:" ++ integer_to_list(Port),
+ ssl_test_lib:version_flag(Version)],
- OpenSslPort = open_port({spawn, Cmd}, [stderr_to_stdout]),
+ OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args),
+
true = port_command(OpenSslPort, Data),
ssl_test_lib:check_result(Server, ok),
@@ -839,12 +838,11 @@ erlang_client_bad_openssl_server(Config) when is_list(Config) ->
CertFile = proplists:get_value(certfile, ServerOpts),
KeyFile = proplists:get_value(keyfile, ServerOpts),
Version = tls_record:protocol_version(tls_record:highest_protocol_version([])),
- Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++ ssl_test_lib:version_flag(Version) ++
- " -cert " ++ CertFile ++ " -key " ++ KeyFile ++ "",
+ Exe = "openssl",
+ Args = ["s_server", "-accept", integer_to_list(Port), ssl_test_lib:version_flag(Version),
+ "-cert", CertFile, "-key", KeyFile],
- ct:log("openssl cmd: ~p~n", [Cmd]),
-
- OpensslPort = open_port({spawn, Cmd}, [stderr_to_stdout]),
+ OpensslPort = ssl_test_lib:portable_open_port(Exe, Args),
ssl_test_lib:wait_for_openssl_server(Port),
@@ -895,12 +893,11 @@ expired_session(Config) when is_list(Config) ->
CertFile = proplists:get_value(certfile, ServerOpts),
KeyFile = proplists:get_value(keyfile, ServerOpts),
- Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++
- " -cert " ++ CertFile ++ " -key " ++ KeyFile ++ "",
+ Exe = "openssl",
+ Args = ["s_server", "-accept", integer_to_list(Port),
+ "-cert", CertFile,"-key", KeyFile],
- ct:log("openssl cmd: ~p~n", [Cmd]),
-
- OpensslPort = open_port({spawn, Cmd}, [stderr_to_stdout]),
+ OpensslPort = ssl_test_lib:portable_open_port(Exe, Args),
ssl_test_lib:wait_for_openssl_server(Port),
@@ -953,12 +950,11 @@ ssl2_erlang_server_openssl_client(Config) when is_list(Config) ->
{options, ServerOpts}]),
Port = ssl_test_lib:inet_port(Server),
- Cmd = "openssl s_client -port " ++ integer_to_list(Port) ++
- " -host localhost -ssl2 -msg",
-
- ct:log("openssl cmd: ~p~n", [Cmd]),
+ Exe = "openssl",
+ Args = ["s_client", "-connect", "localhost:" ++ integer_to_list(Port),
+ "-ssl2", "-msg"],
- OpenSslPort = open_port({spawn, Cmd}, [stderr_to_stdout]),
+ OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args),
true = port_command(OpenSslPort, Data),
ct:log("Ports ~p~n", [[erlang:port_info(P) || P <- erlang:ports()]]),
@@ -1033,7 +1029,7 @@ erlang_server_alpn_openssl_client(Config) when is_list(Config) ->
Data = "From openssl to erlang",
start_erlang_server_and_openssl_client_with_opts(Config,
[{alpn_preferred_protocols, [<<"spdy/2">>]}],
- "",
+ [],
Data, fun(Server, OpensslPort) ->
true = port_command(OpensslPort, Data),
ssl_test_lib:check_result(Server, ok)
@@ -1046,7 +1042,7 @@ erlang_server_openssl_client_alpn(Config) when is_list(Config) ->
Data = "From openssl to erlang",
start_erlang_server_and_openssl_client_with_opts(Config,
[],
- "-alpn spdy/2",
+ ["-alpn", "spdy/2"],
Data, fun(Server, OpensslPort) ->
true = port_command(OpensslPort, Data),
ssl_test_lib:check_result(Server, ok)
@@ -1179,7 +1175,7 @@ erlang_client_openssl_server_npn_only_client(Config) when is_list(Config) ->
%%--------------------------------------------------------------------------
erlang_server_openssl_client_npn_only_server(Config) when is_list(Config) ->
Data = "From openssl to erlang",
- start_erlang_server_and_openssl_client_with_opts(Config, [{next_protocols_advertised, [<<"spdy/2">>]}], "",
+ start_erlang_server_and_openssl_client_with_opts(Config, [{next_protocols_advertised, [<<"spdy/2">>]}], [],
Data, fun(Server, OpensslPort) ->
true = port_command(OpensslPort, Data),
ssl_test_lib:check_result(Server, ok)
@@ -1188,7 +1184,7 @@ erlang_server_openssl_client_npn_only_server(Config) when is_list(Config) ->
erlang_server_openssl_client_npn_only_client(Config) when is_list(Config) ->
Data = "From openssl to erlang",
- start_erlang_server_and_openssl_client_with_opts(Config, [], "-nextprotoneg spdy/2",
+ start_erlang_server_and_openssl_client_with_opts(Config, [], ["-nextprotoneg", "spdy/2"],
Data, fun(Server, OpensslPort) ->
true = port_command(OpensslPort, Data),
ssl_test_lib:check_result(Server, ok)
@@ -1261,7 +1257,7 @@ client_check_result(Port, DataExpected, DataReceived) ->
client_check_result(Port, DataExpected, NewData)
end
after 3000 ->
- ct:fail({"Time out on opensssl Client", {expected, DataExpected},
+ ct:fail({"Time out on openSSL Client", {expected, DataExpected},
{got, DataReceived}})
end.
client_check_result(Port, DataExpected) ->
@@ -1613,12 +1609,12 @@ start_erlang_server_and_openssl_client_for_npn_negotiation(Config, Data, Callbac
{options, ServerOpts}]),
Port = ssl_test_lib:inet_port(Server),
Version = tls_record:protocol_version(tls_record:highest_protocol_version([])),
- Cmd = "openssl s_client -nextprotoneg http/1.0,spdy/2 -msg -port " ++ integer_to_list(Port) ++ ssl_test_lib:version_flag(Version) ++
- " -host localhost",
- ct:log("openssl cmd: ~p~n", [Cmd]),
+ Exe = "openssl",
+ Args = ["s_client", "-nextprotoneg", "http/1.0,spdy/2", "-msg", "-connect", "localhost:"
+ ++ integer_to_list(Port), ssl_test_lib:version_flag(Version)],
- OpenSslPort = open_port({spawn, Cmd}, [stderr_to_stdout]),
+ OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args),
Callback(Server, OpenSslPort),
@@ -1642,12 +1638,12 @@ start_erlang_server_and_openssl_client_with_opts(Config, ErlangServerOpts, OpenS
{options, ServerOpts}]),
Port = ssl_test_lib:inet_port(Server),
Version = tls_record:protocol_version(tls_record:highest_protocol_version([])),
- Cmd = "openssl s_client " ++ OpenSSLClientOpts ++ " -msg -port " ++ integer_to_list(Port) ++ ssl_test_lib:version_flag(Version) ++
- " -host localhost",
+
+ Exe = "openssl",
+ Args = ["s_client"] ++ OpenSSLClientOpts ++ ["-msg", "-connect", "localhost:" ++ integer_to_list(Port),
+ ssl_test_lib:version_flag(Version)],
- ct:log("openssl cmd: ~p~n", [Cmd]),
-
- OpenSslPort = open_port({spawn, Cmd}, [stderr_to_stdout]),
+ OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args),
Callback(Server, OpenSslPort),
@@ -1679,8 +1675,6 @@ erlang_ssl_receive(Socket, Data) ->
erlang_ssl_receive(Socket,Data);
Other ->
ct:fail({unexpected_message, Other})
- after 4000 ->
- ct:fail({did_not_get, Data})
end.
connection_info(Socket, Version) ->
@@ -1753,7 +1747,9 @@ check_sane_openssl_renegotaite(Config, _) ->
check_sane_openssl_renegotaite(Config).
check_sane_openssl_renegotaite(Config) ->
- case os:cmd("openssl version") of
+ case os:cmd("openssl version") of
+ "OpenSSL 1.0.0" ++ _ ->
+ {skip, "Known renegotiation bug in OpenSSL"};
"OpenSSL 0.9.8" ++ _ ->
{skip, "Known renegotiation bug in OpenSSL"};
"OpenSSL 0.9.7" ++ _ ->
@@ -1793,13 +1789,13 @@ workaround_openssl_s_clinent() ->
%% explicitly specified
case os:cmd("openssl version") of
"OpenSSL 1.0.1c" ++ _ ->
- " -no_tls1_2 ";
+ ["-no_tls1_2"];
"OpenSSL 1.0.1d" ++ _ ->
- " -no_tls1_2 ";
+ ["-no_tls1_2"];
"OpenSSL 1.0.1e" ++ _ ->
- " -no_tls1_2 ";
+ ["-no_tls1_2"];
"OpenSSL 1.0.1f" ++ _ ->
- " -no_tls1_2 ";
+ ["-no_tls1_2"];
_ ->
- ""
+ []
end.
diff --git a/lib/ssl/vsn.mk b/lib/ssl/vsn.mk
index 4587c448f6..aa1af21990 100644
--- a/lib/ssl/vsn.mk
+++ b/lib/ssl/vsn.mk
@@ -1 +1 @@
-SSL_VSN = 7.1
+SSL_VSN = 7.2
diff --git a/lib/stdlib/doc/src/rand.xml b/lib/stdlib/doc/src/rand.xml
index e7d4728ef7..50057259c6 100644
--- a/lib/stdlib/doc/src/rand.xml
+++ b/lib/stdlib/doc/src/rand.xml
@@ -104,7 +104,7 @@
strong. If a strong cryptographic random number generator is
needed, use one of functions in the
<seealso marker="crypto:crypto">crypto</seealso>
- module, for example <c>crypto:rand_bytes/1</c>.</p></note>
+ module, for example <c>crypto:strong_rand_bytes/1</c>.</p></note>
</description>
<datatypes>
<datatype>
diff --git a/lib/stdlib/doc/src/random.xml b/lib/stdlib/doc/src/random.xml
index a1bf67d332..fc4f796863 100644
--- a/lib/stdlib/doc/src/random.xml
+++ b/lib/stdlib/doc/src/random.xml
@@ -48,7 +48,7 @@
tuple of three integers.</p>
<p>It should be noted that this random number generator is not cryptographically
strong. If a strong cryptographic random number generator is needed for
- example <c>crypto:rand_bytes/1</c> could be used instead.</p>
+ example <c>crypto:strong_rand_bytes/1</c> could be used instead.</p>
<note><p>The new and improved <seealso
marker="stdlib:rand">rand</seealso> module should be used
instead of this module.</p></note>
@@ -148,7 +148,7 @@ random:seed(erlang:phash2([node()]),
<p>The implementation changed in R15. Upgrading to R15 will break
applications that expect a specific output for a given seed. The output
is still deterministic number series, but different compared to releases
- older than R15. The seed <c>{0,0,0}</c> will for example no longer
+ older than R15. The seed <c>{0,0,0}</c> will, for example, no longer
produce a flawed series of only zeros.</p>
</section>
</erlref>
diff --git a/lib/stdlib/src/epp.erl b/lib/stdlib/src/epp.erl
index c8bba579cc..45f616bb02 100644
--- a/lib/stdlib/src/epp.erl
+++ b/lib/stdlib/src/epp.erl
@@ -40,7 +40,7 @@
-type ifdef() :: 'ifdef' | 'ifndef' | 'else'.
--type name() :: {'atom', atom()}.
+-type name() :: atom().
-type argspec() :: 'none' %No arguments
| non_neg_integer(). %Number of arguments
-type tokens() :: [erl_scan:token()].
@@ -58,21 +58,14 @@
istk=[] :: [ifdef()], %Ifdef stack
sstk=[] :: [#epp{}], %State stack
path=[] :: [file:name()], %Include-path
- macs = dict:new() %Macros (don't care locations)
- :: dict:dict(name(), {argspec(), tokens()}),
- uses = dict:new() %Macro use structure
- :: dict:dict(name(), [{argspec(), [used()]}]),
+ macs = #{} %Macros (don't care locations)
+ :: #{name() => {argspec(), tokens()}},
+ uses = #{} %Macro use structure
+ :: #{name() => [{argspec(), [used()]}]},
default_encoding = ?DEFAULT_ENCODING :: source_encoding(),
pre_opened = false :: boolean()
}).
-%%% Note on representation: as tokens, both {var, Location, Name} and
-%%% {atom, Location, Name} can occur as macro identifiers. However, keeping
-%%% this distinction here is done for historical reasons only: previously,
-%%% ?FOO and ?'FOO' were not the same, but now they are. Removing the
-%%% distinction in the internal representation would simplify the code
-%%% a little.
-
%% open(Options)
%% open(FileName, IncludePath)
%% open(FileName, IncludePath, PreDefMacros)
@@ -550,7 +543,8 @@ init_server(Pid, Name, Options, St0) ->
default_encoding=DefEncoding},
From = wait_request(St),
Anno = erl_anno:new(AtLocation),
- enter_file_reply(From, Name, Anno, AtLocation, code),
+ enter_file_reply(From, file_name(Name), Anno,
+ AtLocation, code),
wait_req_scan(St);
{error,E} ->
epp_reply(Pid, {error,E})
@@ -561,18 +555,18 @@ init_server(Pid, Name, Options, St0) ->
%% FILE, LINE, MODULE as undefined, MACHINE and MACHINE value.
predef_macros(File) ->
- Machine = list_to_atom(erlang:system_info(machine)),
- Anno = line1(),
- dict:from_list([
- {{atom,'FILE'}, {none,[{string,Anno,File}]}},
- {{atom,'LINE'}, {none,[{integer,Anno,1}]}},
- {{atom,'MODULE'}, undefined},
- {{atom,'MODULE_STRING'}, undefined},
- {{atom,'BASE_MODULE'}, undefined},
- {{atom,'BASE_MODULE_STRING'}, undefined},
- {{atom,'MACHINE'}, {none,[{atom,Anno,Machine}]}},
- {{atom,Machine}, {none,[{atom,Anno,true}]}}
- ]).
+ Machine = list_to_atom(erlang:system_info(machine)),
+ Anno = line1(),
+ Defs = [{'FILE', {none,[{string,Anno,File}]}},
+ {'LINE', {none,[{integer,Anno,1}]}},
+ {'MODULE', undefined},
+ {'MODULE_STRING', undefined},
+ {'BASE_MODULE', undefined},
+ {'BASE_MODULE_STRING', undefined},
+ {'MACHINE', {none,[{atom,Anno,Machine}]}},
+ {Machine, {none,[{atom,Anno,true}]}}
+ ],
+ maps:from_list(Defs).
%% user_predef(PreDefMacros, Macros) ->
%% {ok,MacroDict} | {error,E}
@@ -581,28 +575,21 @@ predef_macros(File) ->
user_predef([{M,Val,redefine}|Pdm], Ms) when is_atom(M) ->
Exp = erl_parse:tokens(erl_parse:abstract(Val)),
- user_predef(Pdm, dict:store({atom,M}, {none,Exp}, Ms));
+ user_predef(Pdm, Ms#{M=>{none,Exp}});
user_predef([{M,Val}|Pdm], Ms) when is_atom(M) ->
- case dict:find({atom,M}, Ms) of
- {ok,_Defs} when is_list(_Defs) -> %% User defined macros
+ case Ms of
+ #{M:=Defs} when is_list(Defs) ->
+ %% User defined macros.
{error,{redefine,M}};
- {ok,_Def} -> %% Predefined macros
+ #{M:=_Defs} ->
+ %% Predefined macros.
{error,{redefine_predef,M}};
- error ->
+ _ ->
Exp = erl_parse:tokens(erl_parse:abstract(Val)),
- user_predef(Pdm, dict:store({atom,M}, [{none, {none,Exp}}], Ms))
+ user_predef(Pdm, Ms#{M=>[{none,{none,Exp}}]})
end;
user_predef([M|Pdm], Ms) when is_atom(M) ->
- case dict:find({atom,M}, Ms) of
- {ok,_Defs} when is_list(_Defs) -> %% User defined macros
- {error,{redefine,M}};
- {ok,_Def} -> %% Predefined macros
- {error,{redefine_predef,M}};
- error ->
- A = line1(),
- user_predef(Pdm,
- dict:store({atom,M}, [{none, {none,[{atom,A,true}]}}], Ms))
- end;
+ user_predef([{M,true}|Pdm], Ms);
user_predef([Md|_Pdm], _Ms) -> {error,{bad,Md}};
user_predef([], Ms) -> {ok,Ms}.
@@ -616,7 +603,9 @@ wait_request(St) ->
receive
{epp_request,From,scan_erl_form} -> From;
{epp_request,From,macro_defs} ->
- epp_reply(From, dict:to_list(St#epp.macs)),
+ %% Return the old format to avoid any incompability issues.
+ Defs = [{{atom,K},V} || {K,V} <- maps:to_list(St#epp.macs)],
+ epp_reply(From, Defs),
wait_request(St);
{epp_request,From,close} ->
close_file(St),
@@ -668,7 +657,8 @@ enter_file(NewName, Inc, From, St) ->
enter_file2(NewF, Pname, From, St0, AtLocation) ->
Anno = erl_anno:new(AtLocation),
enter_file_reply(From, Pname, Anno, AtLocation, code),
- Ms = dict:store({atom,'FILE'}, {none,[{string,Anno,Pname}]}, St0#epp.macs),
+ Ms0 = St0#epp.macs,
+ Ms = Ms0#{'FILE':={none,[{string,Anno,Pname}]}},
%% update the head of the include path to be the directory of the new
%% source file, so that an included file can always include other files
%% relative to its current location (this is also how C does it); note
@@ -689,7 +679,7 @@ enter_file_reply(From, Name, LocationAnno, AtLocation, Where) ->
generated -> erl_anno:set_generated(true, Anno0)
end,
Rep = {ok, [{'-',Anno},{atom,Anno,file},{'(',Anno},
- {string,Anno,file_name(Name)},{',',Anno},
+ {string,Anno,Name},{',',Anno},
{integer,Anno,get_line(LocationAnno)},{')',LocationAnno},
{dot,Anno}]},
epp_reply(From, Rep).
@@ -720,9 +710,8 @@ leave_file(From, St) ->
name2=OldName2} = OldSt,
CurrLoc = add_line(OldLoc, Delta),
Anno = erl_anno:new(CurrLoc),
- Ms = dict:store({atom,'FILE'},
- {none,[{string,Anno,OldName2}]},
- St#epp.macs),
+ Ms0 = St#epp.macs,
+ Ms = Ms0#{'FILE':={none,[{string,Anno,OldName2}]}},
NextSt = OldSt#epp{sstk=Sts,macs=Ms,uses=St#epp.uses},
enter_file_reply(From, OldName, Anno, CurrLoc, code),
case OldName2 =:= OldName of
@@ -797,91 +786,48 @@ scan_toks(Toks0, From, St) ->
end.
scan_module([{'-',_Lh},{atom,_Lm,module},{'(',_Ll}|Ts], Ms) ->
- scan_module_1(Ts, [], Ms);
+ scan_module_1(Ts, Ms);
scan_module([{'-',_Lh},{atom,_Lm,extends},{'(',_Ll}|Ts], Ms) ->
- scan_extends(Ts, [], Ms);
+ scan_extends(Ts, Ms);
scan_module(_Ts, Ms) -> Ms.
-scan_module_1([{atom,_,_}=A,{',',L}|Ts], As, Ms) ->
+scan_module_1([{atom,_,_}=A,{',',L}|Ts], Ms) ->
%% Parameterized modules.
- scan_module_1([A,{')',L}|Ts], As, Ms);
-scan_module_1([{atom,Ln,A},{')',_Lr}|_Ts], As, Ms0) ->
- Mod = lists:concat(lists:reverse([A|As])),
- Ms = dict:store({atom,'MODULE'},
- {none,[{atom,Ln,list_to_atom(Mod)}]}, Ms0),
- dict:store({atom,'MODULE_STRING'}, {none,[{string,Ln,Mod}]}, Ms);
-scan_module_1([{atom,_Ln,A},{'.',_Lr}|Ts], As, Ms) ->
- scan_module_1(Ts, [".",A|As], Ms);
-scan_module_1([{'.',_Lr}|Ts], As, Ms) ->
- scan_module_1(Ts, As, Ms);
-scan_module_1(_Ts, _As, Ms) -> Ms.
-
-scan_extends([{atom,Ln,A},{')',_Lr}|_Ts], As, Ms0) ->
- Mod = lists:concat(lists:reverse([A|As])),
- Ms = dict:store({atom,'BASE_MODULE'},
- {none,[{atom,Ln,list_to_atom(Mod)}]}, Ms0),
- dict:store({atom,'BASE_MODULE_STRING'}, {none,[{string,Ln,Mod}]}, Ms);
-scan_extends([{atom,_Ln,A},{'.',_Lr}|Ts], As, Ms) ->
- scan_extends(Ts, [".",A|As], Ms);
-scan_extends([{'.',_Lr}|Ts], As, Ms) ->
- scan_extends(Ts, As, Ms);
-scan_extends(_Ts, _As, Ms) -> Ms.
+ scan_module_1([A,{')',L}|Ts], Ms);
+scan_module_1([{atom,Ln,A}=ModAtom,{')',_Lr}|_Ts], Ms0) ->
+ ModString = atom_to_list(A),
+ Ms = Ms0#{'MODULE':={none,[ModAtom]}},
+ Ms#{'MODULE_STRING':={none,[{string,Ln,ModString}]}};
+scan_module_1(_Ts, Ms) -> Ms.
+
+scan_extends([{atom,Ln,A}=ModAtom,{')',_Lr}|_Ts], Ms0) ->
+ ModString = atom_to_list(A),
+ Ms = Ms0#{'BASE_MODULE':={none,[ModAtom]}},
+ Ms#{'BASE_MODULE_STRING':={none,[{string,Ln,ModString}]}};
+scan_extends(_Ts, Ms) -> Ms.
%% scan_define(Tokens, DefineToken, From, EppState)
-scan_define([{'(',_Lp},{Type,_Lm,M}=Mac,{',',_}=Comma|Toks], _Def, From, St)
+scan_define([{'(',_Lp},{Type,_Lm,_}=Mac|Toks], Def, From, St)
when Type =:= atom; Type =:= var ->
+ scan_define_1(Toks, Mac, Def, From, St);
+scan_define(_Toks, Def, From, St) ->
+ epp_reply(From, {error,{loc(Def),epp,{bad,define}}}),
+ wait_req_scan(St).
+
+scan_define_1([{',',_}=Comma|Toks], Mac,_Def, From, St) ->
case catch macro_expansion(Toks, Comma) of
Expansion when is_list(Expansion) ->
- case dict:find({atom,M}, St#epp.macs) of
- {ok, Defs} when is_list(Defs) ->
- %% User defined macros: can be overloaded
- case proplists:is_defined(none, Defs) of
- true ->
- epp_reply(From, {error,{loc(Mac),epp,{redefine,M}}}),
- wait_req_scan(St);
- false ->
- scan_define_cont(From, St,
- {atom, M},
- {none, {none,Expansion}})
- end;
- {ok, _PreDef} ->
- %% Predefined macros: cannot be overloaded
- epp_reply(From, {error,{loc(Mac),epp,{redefine_predef,M}}}),
- wait_req_scan(St);
- error ->
- scan_define_cont(From, St,
- {atom, M},
- {none, {none,Expansion}})
- end;
+ scan_define_2(none, {none,Expansion}, Mac, From, St);
{error,ErrL,What} ->
epp_reply(From, {error,{ErrL,epp,What}}),
wait_req_scan(St)
end;
-scan_define([{'(',_Lp},{Type,_Lm,M}=Mac,{'(',_Lc}|Toks], Def, From, St)
- when Type =:= atom; Type =:= var ->
+scan_define_1([{'(',_Lc}|Toks], Mac, Def, From, St) ->
case catch macro_pars(Toks, []) of
- {ok, {As,Me}} ->
+ {ok,{As,_}=MacroDef} ->
Len = length(As),
- case dict:find({atom,M}, St#epp.macs) of
- {ok, Defs} when is_list(Defs) ->
- %% User defined macros: can be overloaded
- case proplists:is_defined(Len, Defs) of
- true ->
- epp_reply(From,{error,{loc(Mac),epp,{redefine,M}}}),
- wait_req_scan(St);
- false ->
- scan_define_cont(From, St, {atom, M},
- {Len, {As, Me}})
- end;
- {ok, _PreDef} ->
- %% Predefined macros: cannot be overloaded
- %% (There are currently no predefined F(...) macros.)
- epp_reply(From, {error,{loc(Mac),epp,{redefine_predef,M}}}),
- wait_req_scan(St);
- error ->
- scan_define_cont(From, St, {atom, M}, {Len, {As, Me}})
- end;
+ scan_define_2(Len, MacroDef, Mac, From, St);
{error,ErrL,What} ->
epp_reply(From, {error,{ErrL,epp,What}}),
wait_req_scan(St);
@@ -889,10 +835,29 @@ scan_define([{'(',_Lp},{Type,_Lm,M}=Mac,{'(',_Lc}|Toks], Def, From, St)
epp_reply(From, {error,{loc(Def),epp,{bad,define}}}),
wait_req_scan(St)
end;
-scan_define(_Toks, Def, From, St) ->
+scan_define_1(_Toks, _Mac, Def, From, St) ->
epp_reply(From, {error,{loc(Def),epp,{bad,define}}}),
wait_req_scan(St).
+scan_define_2(Arity, Def, {_,_,Key}=Mac, From, #epp{macs=Ms}=St) ->
+ case Ms of
+ #{Key:=Defs} when is_list(Defs) ->
+ %% User defined macros: can be overloaded
+ case proplists:is_defined(Arity, Defs) of
+ true ->
+ epp_reply(From, {error,{loc(Mac),epp,{redefine,Key}}}),
+ wait_req_scan(St);
+ false ->
+ scan_define_cont(From, St, Key, Defs, Arity, Def)
+ end;
+ #{Key:=_} ->
+ %% Predefined macros: cannot be overloaded
+ epp_reply(From, {error,{loc(Mac),epp,{redefine_predef,Key}}}),
+ wait_req_scan(St);
+ _ ->
+ scan_define_cont(From, St, Key, [], Arity, Def)
+ end.
+
%%% Detection of circular macro expansions (which would either keep
%%% the compiler looping forever, or run out of memory):
%%% When a macro is defined, we store the names of other macros it
@@ -902,11 +867,17 @@ scan_define(_Toks, Def, From, St) ->
%%% the information from St#epp.uses is traversed, and if a circularity
%%% is detected, an error message is thrown.
-scan_define_cont(F, St, M, {Arity, Def}) ->
- Ms = dict:append_list(M, [{Arity, Def}], St#epp.macs),
- try dict:append_list(M, [{Arity, macro_uses(Def)}], St#epp.uses) of
+scan_define_cont(F, #epp{macs=Ms0}=St, M, Defs, Arity, Def) ->
+ Ms = Ms0#{M=>[{Arity,Def}|Defs]},
+ try macro_uses(Def) of
U ->
- scan_toks(F, St#epp{uses=U, macs=Ms})
+ Uses0 = St#epp.uses,
+ Val = [{Arity,U}|case Uses0 of
+ #{M:=UseList} -> UseList;
+ _ -> []
+ end],
+ Uses = Uses0#{M=>Val},
+ scan_toks(F, St#epp{uses=Uses,macs=Ms})
catch
{error, Line, Reason} ->
epp_reply(F, {error,{Line,epp,Reason}}),
@@ -924,23 +895,23 @@ macro_ref([{'?', _}, {'?', _} | Rest]) ->
macro_ref([{'?', _}, {atom, _, A}=Atom | Rest]) ->
Lm = loc(Atom),
Arity = count_args(Rest, Lm, A),
- [{{atom, A}, Arity} | macro_ref(Rest)];
+ [{A,Arity} | macro_ref(Rest)];
macro_ref([{'?', _}, {var, _, A}=Var | Rest]) ->
Lm = loc(Var),
Arity = count_args(Rest, Lm, A),
- [{{atom, A}, Arity} | macro_ref(Rest)];
+ [{A,Arity} | macro_ref(Rest)];
macro_ref([_Token | Rest]) ->
macro_ref(Rest).
%% scan_undef(Tokens, UndefToken, From, EppState)
scan_undef([{'(',_Llp},{atom,_Lm,M},{')',_Lrp},{dot,_Ld}], _Undef, From, St) ->
- Macs = dict:erase({atom,M}, St#epp.macs),
- Uses = dict:erase({atom,M}, St#epp.uses),
+ Macs = maps:remove(M, St#epp.macs),
+ Uses = maps:remove(M, St#epp.uses),
scan_toks(From, St#epp{macs=Macs, uses=Uses});
scan_undef([{'(',_Llp},{var,_Lm,M},{')',_Lrp},{dot,_Ld}], _Undef, From,St) ->
- Macs = dict:erase({atom,M}, St#epp.macs),
- Uses = dict:erase({atom,M}, St#epp.uses),
+ Macs = maps:remove(M, St#epp.macs),
+ Uses = maps:remove(M, St#epp.uses),
scan_toks(From, St#epp{macs=Macs, uses=Uses});
scan_undef(_Toks, Undef, From, St) ->
epp_reply(From, {error,{loc(Undef),epp,{bad,undef}}}),
@@ -1007,17 +978,17 @@ scan_include_lib(_Toks, Inc, From, St) ->
%% Report a badly formed if[n]def test and then treat as undefined macro.
scan_ifdef([{'(',_Llp},{atom,_Lm,M},{')',_Lrp},{dot,_Ld}], _IfD, From, St) ->
- case dict:find({atom,M}, St#epp.macs) of
- {ok,_Def} ->
+ case St#epp.macs of
+ #{M:=_Def} ->
scan_toks(From, St#epp{istk=[ifdef|St#epp.istk]});
- error ->
+ _ ->
skip_toks(From, St, [ifdef])
end;
scan_ifdef([{'(',_Llp},{var,_Lm,M},{')',_Lrp},{dot,_Ld}], _IfD, From, St) ->
- case dict:find({atom,M}, St#epp.macs) of
- {ok,_Def} ->
+ case St#epp.macs of
+ #{M:=_Def} ->
scan_toks(From, St#epp{istk=[ifdef|St#epp.istk]});
- error ->
+ _ ->
skip_toks(From, St, [ifdef])
end;
scan_ifdef(_Toks, IfDef, From, St) ->
@@ -1025,17 +996,17 @@ scan_ifdef(_Toks, IfDef, From, St) ->
wait_req_skip(St, [ifdef]).
scan_ifndef([{'(',_Llp},{atom,_Lm,M},{')',_Lrp},{dot,_Ld}], _IfnD, From, St) ->
- case dict:find({atom,M}, St#epp.macs) of
- {ok,_Def} ->
+ case St#epp.macs of
+ #{M:=_Def} ->
skip_toks(From, St, [ifndef]);
- error ->
+ _ ->
scan_toks(From, St#epp{istk=[ifndef|St#epp.istk]})
end;
scan_ifndef([{'(',_Llp},{var,_Lm,M},{')',_Lrp},{dot,_Ld}], _IfnD, From, St) ->
- case dict:find({atom,M}, St#epp.macs) of
- {ok,_Def} ->
+ case St#epp.macs of
+ #{M:=_Def} ->
skip_toks(From, St, [ifndef]);
- error ->
+ _ ->
scan_toks(From, St#epp{istk=[ifndef|St#epp.istk]})
end;
scan_ifndef(_Toks, IfnDef, From, St) ->
@@ -1103,7 +1074,8 @@ scan_file([{'(',_Llp},{string,_Ls,Name},{',',_Lc},{integer,_Li,Ln},{')',_Lrp},
{dot,_Ld}], Tf, From, St) ->
Anno = erl_anno:new(Ln),
enter_file_reply(From, Name, Anno, loc(Tf), generated),
- Ms = dict:store({atom,'FILE'}, {none,[{string,line1(),Name}]}, St#epp.macs),
+ Ms0 = St#epp.macs,
+ Ms = Ms0#{'FILE':={none,[{string,line1(),Name}]}},
Locf = loc(Tf),
NewLoc = new_location(Ln, St#epp.location, Locf),
Delta = get_line(element(2, Tf))-Ln + St#epp.delta,
@@ -1191,40 +1163,42 @@ macro_expansion([], Anno0) -> throw({error,loc(Anno0),premature_end}).
%% Expand the macros in a list of tokens, making sure that an expansion
%% gets the same location as the macro call.
-expand_macros(Type, MacT, M, Toks, Ms0) ->
- %% (Type will always be 'atom')
- {Ms, U} = Ms0,
+expand_macros(MacT, M, Toks, Ms0) ->
+ {Ms,U} = Ms0,
Lm = loc(MacT),
Tinfo = element(2, MacT),
- case expand_macro1(Type, Lm, M, Toks, Ms) of
+ case expand_macro1(Lm, M, Toks, Ms) of
{ok,{none,Exp}} ->
- check_uses([{{Type,M}, none}], [], U, Lm),
- Toks1 = expand_macros(expand_macro(Exp, Tinfo, [], dict:new()), Ms0),
+ check_uses([{M,none}], [], U, Lm),
+ Toks1 = expand_macros(expand_macro(Exp, Tinfo, [], #{}), Ms0),
expand_macros(Toks1++Toks, Ms0);
{ok,{As,Exp}} ->
- check_uses([{{Type,M}, length(As)}], [], U, Lm),
- {Bs,Toks1} = bind_args(Toks, Lm, M, As, dict:new()),
+ check_uses([{M,length(As)}], [], U, Lm),
+ {Bs,Toks1} = bind_args(Toks, Lm, M, As, #{}),
expand_macros(expand_macro(Exp, Tinfo, Toks1, Bs), Ms0)
end.
-expand_macro1(Type, Lm, M, Toks, Ms) ->
+expand_macro1(Lm, M, Toks, Ms) ->
Arity = count_args(Toks, Lm, M),
- case dict:find({Type,M}, Ms) of
- error -> %% macro not found
- throw({error,Lm,{undefined,M,Arity}});
- {ok, undefined} -> %% Predefined macro without definition
+ case Ms of
+ #{M:=undefined} ->
+ %% Predefined macro without definition.
throw({error,Lm,{undefined,M,Arity}});
- {ok, [{none, Def}]} ->
- {ok, Def};
- {ok, Defs} when is_list(Defs) ->
- case proplists:get_value(Arity, Defs) of
+ #{M:=[{none,Def}]} ->
+ {ok,Def};
+ #{M:=Defs} when is_list(Defs) ->
+ case proplists:get_value(Arity, Defs) of
undefined ->
throw({error,Lm,{mismatch,M}});
Def ->
- {ok, Def}
+ {ok,Def}
end;
- {ok, PreDef} -> %% Predefined macro
- {ok, PreDef}
+ #{M:=PreDef} ->
+ %% Predefined macro.
+ {ok,PreDef};
+ _ ->
+ %% Macro not found.
+ throw({error,Lm,{undefined,M,Arity}})
end.
check_uses([], _Anc, _U, _Lm) ->
@@ -1232,7 +1206,7 @@ check_uses([], _Anc, _U, _Lm) ->
check_uses([M|Rest], Anc, U, Lm) ->
case lists:member(M, Anc) of
true ->
- {{_, Name},Arity} = M,
+ {Name,Arity} = M,
throw({error,Lm,{circular,Name,Arity}});
false ->
L = get_macro_uses(M, U),
@@ -1241,23 +1215,23 @@ check_uses([M|Rest], Anc, U, Lm) ->
end.
get_macro_uses({M,Arity}, U) ->
- case dict:find(M, U) of
- error ->
- [];
- {ok, L} ->
- proplists:get_value(Arity, L, proplists:get_value(none, L, []))
+ case U of
+ #{M:=L} ->
+ proplists:get_value(Arity, L, proplists:get_value(none, L, []));
+ _ ->
+ []
end.
%% Macro expansion
%% Note: io:scan_erl_form() does not return comments or white spaces.
expand_macros([{'?',_Lq},{atom,_Lm,M}=MacT|Toks], Ms) ->
- expand_macros(atom, MacT, M, Toks, Ms);
+ expand_macros(MacT, M, Toks, Ms);
%% Special macros
expand_macros([{'?',_Lq},{var,Lm,'LINE'}=Tok|Toks], Ms) ->
Line = erl_scan:line(Tok),
[{integer,Lm,Line}|expand_macros(Toks, Ms)];
expand_macros([{'?',_Lq},{var,_Lm,M}=MacT|Toks], Ms) ->
- expand_macros(atom, MacT, M, Toks, Ms);
+ expand_macros(MacT, M, Toks, Ms);
%% Illegal macros
expand_macros([{'?',_Lq},Token|_Toks], _Ms) ->
T = case erl_scan:text(Token) of
@@ -1296,7 +1270,7 @@ macro_args(_Toks, Lm, M, _As, _Bs) ->
store_arg(L, M, _A, [], _Bs) ->
throw({error,L,{mismatch,M}});
store_arg(_L, _M, A, Arg, Bs) ->
- dict:store(A, Arg, Bs).
+ Bs#{A=>Arg}.
%% count_args(Tokens, MacroLine, MacroName)
%% Count the number of arguments in a macro call.
@@ -1369,19 +1343,17 @@ macro_arg([], _E, Arg) ->
%% and then the macro arguments, i.e. simulate textual expansion.
expand_macro([{var,_Lv,V}|Ts], L, Rest, Bs) ->
- case dict:find(V, Bs) of
- {ok,Val} ->
- %% lists:append(Val, expand_macro(Ts, L, Rest, Bs));
+ case Bs of
+ #{V:=Val} ->
expand_arg(Val, Ts, L, Rest, Bs);
- error ->
+ _ ->
[{var,L,V}|expand_macro(Ts, L, Rest, Bs)]
end;
expand_macro([{'?', _}, {'?', _}, {var,_Lv,V}|Ts], L, Rest, Bs) ->
- case dict:find(V, Bs) of
- {ok,Val} ->
- %% lists:append(Val, expand_macro(Ts, L, Rest, Bs));
+ case Bs of
+ #{V:=Val} ->
expand_arg(stringify(Val, L), Ts, L, Rest, Bs);
- error ->
+ _ ->
[{var,L,V}|expand_macro(Ts, L, Rest, Bs)]
end;
expand_macro([T|Ts], L, Rest, Bs) ->
diff --git a/lib/stdlib/src/erl_lint.erl b/lib/stdlib/src/erl_lint.erl
index a5f0e7dbd3..3ce6abe752 100644
--- a/lib/stdlib/src/erl_lint.erl
+++ b/lib/stdlib/src/erl_lint.erl
@@ -292,6 +292,9 @@ format_error({variable_in_record_def,V}) ->
%% --- binaries ---
format_error({undefined_bittype,Type}) ->
io_lib:format("bit type ~w undefined", [Type]);
+format_error({bittype_mismatch,Val1,Val2,What}) ->
+ io_lib:format("conflict in ~s specification for bit field: '~p' and '~p'",
+ [What,Val1,Val2]);
format_error(bittype_unit) ->
"a bit unit size must not be specified unless a size is specified too";
format_error(illegal_bitsize) ->
@@ -370,9 +373,9 @@ format_error({spec_fun_undefined, {F, A}}) ->
format_error({missing_spec, {F,A}}) ->
io_lib:format("missing specification for function ~w/~w", [F, A]);
format_error(spec_wrong_arity) ->
- "spec has the wrong arity";
+ "spec has wrong arity";
format_error(callback_wrong_arity) ->
- "callback has the wrong arity";
+ "callback has wrong arity";
format_error({deprecated_builtin_type, {Name, Arity},
Replacement, Rel}) ->
UseS = case Replacement of
@@ -2875,7 +2878,7 @@ spec_decl(Line, MFA0, TypeSpecs, St0 = #lint{specs = Specs, module = Mod}) ->
St1 = St0#lint{specs = dict:store(MFA, Line, Specs)},
case dict:is_key(MFA, Specs) of
true -> add_error(Line, {redefine_spec, MFA0}, St1);
- false -> check_specs(TypeSpecs, Arity, St1)
+ false -> check_specs(TypeSpecs, spec_wrong_arity, Arity, St1)
end.
%% callback_decl(Line, Fun, Types, State) -> State.
@@ -2889,7 +2892,8 @@ callback_decl(Line, MFA0, TypeSpecs,
St1 = St0#lint{callbacks = dict:store(MFA, Line, Callbacks)},
case dict:is_key(MFA, Callbacks) of
true -> add_error(Line, {redefine_callback, MFA0}, St1);
- false -> check_specs(TypeSpecs, Arity, St1)
+ false -> check_specs(TypeSpecs, callback_wrong_arity,
+ Arity, St1)
end
end.
@@ -2926,7 +2930,7 @@ is_fa({FuncName, Arity})
when is_atom(FuncName), is_integer(Arity), Arity >= 0 -> true;
is_fa(_) -> false.
-check_specs([FunType|Left], Arity, St0) ->
+check_specs([FunType|Left], ETag, Arity, St0) ->
{FunType1, CTypes} =
case FunType of
{type, _, bounded_fun, [FT = {type, _, 'fun', _}, Cs]} ->
@@ -2934,18 +2938,16 @@ check_specs([FunType|Left], Arity, St0) ->
{FT, lists:append(Types0)};
{type, _, 'fun', _} = FT -> {FT, []}
end,
- SpecArity =
- case FunType1 of
- {type, L, 'fun', [any, _]} -> any;
- {type, L, 'fun', [{type, _, product, D}, _]} -> length(D)
- end,
+ {type, L, 'fun', [{type, _, product, D}, _]} = FunType1,
+ SpecArity = length(D),
St1 = case Arity =:= SpecArity of
true -> St0;
- false -> add_error(L, spec_wrong_arity, St0)
+ false -> %% Cannot happen if called from the compiler.
+ add_error(L, ETag, St0)
end,
St2 = check_type({type, nowarn(), product, [FunType1|CTypes]}, St1),
- check_specs(Left, Arity, St2);
-check_specs([], _Arity, St) ->
+ check_specs(Left, ETag, Arity, St2);
+check_specs([], _ETag, _Arity, St) ->
St.
nowarn() ->
@@ -3189,8 +3191,8 @@ handle_generator(P,E,Vt,Uvt,St0) ->
handle_bitstring_gen_pat({bin,_,Segments=[_|_]},St) ->
case lists:last(Segments) of
{bin_element,Line,{var,_,_},default,Flags} when is_list(Flags) ->
- case member(binary, Flags) orelse member(bits, Flags)
- orelse member(bitstring, Flags) of
+ case member(binary, Flags) orelse member(bytes, Flags)
+ orelse member(bits, Flags) orelse member(bitstring, Flags) of
true ->
add_error(Line, unsized_binary_in_bin_gen_pattern, St);
false ->
diff --git a/lib/stdlib/src/erl_parse.yrl b/lib/stdlib/src/erl_parse.yrl
index ae42a8f0b1..e07ab2efc2 100644
--- a/lib/stdlib/src/erl_parse.yrl
+++ b/lib/stdlib/src/erl_parse.yrl
@@ -85,10 +85,6 @@ type_spec -> '(' spec_fun type_sigs ')' : {'$2', '$3'}.
spec_fun -> atom : '$1'.
spec_fun -> atom ':' atom : {'$1', '$3'}.
-%% The following two are retained only for backwards compatibility;
-%% they are not part of the EEP syntax and should be removed.
-spec_fun -> atom '/' integer '::' : {'$1', '$3'}.
-spec_fun -> atom ':' atom '/' integer '::' : {'$1', '$3', '$5'}.
typed_attr_val -> expr ',' typed_record_fields : {typed_record, '$1', '$3'}.
typed_attr_val -> expr '::' top_type : {type_def, '$1', '$3'}.
@@ -634,14 +630,8 @@ build_type_spec({Kind,Aa}, {SpecFun, TypeSpecs})
{atom, _, Fun} ->
{Fun, find_arity_from_specs(TypeSpecs)};
{{atom,_, Mod}, {atom,_, Fun}} ->
- {Mod,Fun,find_arity_from_specs(TypeSpecs)};
- {{atom, _, Fun}, {integer, _, Arity}} ->
- %% Old style spec. Allow this for now.
- {Fun,Arity};
- {{atom,_, Mod}, {atom, _, Fun}, {integer, _, Arity}} ->
- %% Old style spec. Allow this for now.
- {Mod,Fun,Arity}
- end,
+ {Mod,Fun,find_arity_from_specs(TypeSpecs)}
+ end,
{attribute,Aa,Kind,{NewSpecFun, TypeSpecs}}.
find_arity_from_specs([Spec|_]) ->
diff --git a/lib/stdlib/src/erl_pp.erl b/lib/stdlib/src/erl_pp.erl
index f7a969977a..c5177aca90 100644
--- a/lib/stdlib/src/erl_pp.erl
+++ b/lib/stdlib/src/erl_pp.erl
@@ -253,6 +253,8 @@ lattribute(import, Name, _Opts, _State) when is_list(Name) ->
attr("import", [{var,a0(),pname(Name)}]);
lattribute(import, {From,Falist}, _Opts, _State) ->
attr("import",[{var,a0(),pname(From)},falist(Falist)]);
+lattribute(export_type, Talist, _Opts, _State) ->
+ call({var,a0(),"-export_type"}, [falist(Talist)], 0, options(none));
lattribute(optional_callbacks, Falist, Opts, _State) ->
ArgL = try falist(Falist)
catch _:_ -> abstract(Falist, Opts)
@@ -321,7 +323,6 @@ ltype({type,_,'fun',[{type,_,any},_]}=FunType, _) ->
ltype({type,_Line,'fun',[{type,_,product,_},_]}=FunType, _) ->
[fun_type(['fun',$(], FunType),$)];
ltype({type,Line,T,Ts}, _) ->
- %% Compatibility. Before 18.0.
simple_type({atom,Line,T}, Ts);
ltype({user_type,Line,T,Ts}, _) ->
simple_type({atom,Line,T}, Ts);
@@ -346,16 +347,8 @@ map_type(Fs) ->
map_pair_types(Fs) ->
tuple_type(Fs, fun map_pair_type/2).
-map_pair_type({type,_Line,map_field_assoc,[Ktype,Vtype]}, Prec) ->
- map_assoc_typed(ltype(Ktype), Vtype, Prec).
-
-map_assoc_typed(B, {type,_,union,Ts}, Prec) ->
- {first,[B,$\s],{seq,[],[],[],map_assoc_union_type(Ts, Prec)}};
-map_assoc_typed(B, Type, Prec) ->
- {list,[{cstep,[B," =>"],ltype(Type, Prec)}]}.
-
-map_assoc_union_type([T|Ts], Prec) ->
- [[leaf("=> "),ltype(T)] | ltypes(Ts, fun union_elem/2, Prec)].
+map_pair_type({type,_Line,map_field_assoc,[KType,VType]}, Prec) ->
+ {list,[{cstep,[ltype(KType, Prec),leaf(" =>")],ltype(VType, Prec)}]}.
record_type(Name, Fields) ->
{first,[record_name(Name)],field_types(Fields)}.
@@ -370,9 +363,6 @@ typed(B, Type) ->
{_L,_P,R} = type_inop_prec('::'),
{list,[{cstep,[B,' ::'],ltype(Type, R)}]}.
-union_elem(T, Prec) ->
- [leaf(" | "),ltype(T, Prec)].
-
tuple_type(Ts, F) ->
{seq,${,$},[$,],ltypes(Ts, F, 0)}.
@@ -399,6 +389,9 @@ guard_type(Before, Gs) ->
Gl = {list,[{step,'when',expr_list(Gs, [$,], fun constraint/2, Opts)}]},
{list,[{step,Before,Gl}]}.
+constraint({type,_Line,constraint,[{atom,_,is_subtype},[{var,_,_}=V,Type]]},
+ _Opts) ->
+ typed(lexpr(V, options(none)), Type);
constraint({type,_Line,constraint,[Tag,As]}, _Opts) ->
simple_type(Tag, As).
diff --git a/lib/stdlib/src/io.erl b/lib/stdlib/src/io.erl
index 284f2e5a2b..5dc8b4541e 100644
--- a/lib/stdlib/src/io.erl
+++ b/lib/stdlib/src/io.erl
@@ -631,41 +631,20 @@ io_requests(Pid, [], [Rs|Cont], Tail) ->
io_requests(_Pid, [], [], _Tail) ->
{false,[]}.
-
-bc_req(Pid,{Op,Enc,Param},MaybeConvert) ->
- case net_kernel:dflag_unicode_io(Pid) of
- true ->
- {false,{Op,Enc,Param}};
- false ->
- {MaybeConvert,{Op,Param}}
- end;
-bc_req(Pid,{Op,Enc,P,F},MaybeConvert) ->
- case net_kernel:dflag_unicode_io(Pid) of
- true ->
- {false,{Op,Enc,P,F}};
- false ->
- {MaybeConvert,{Op,P,F}}
- end;
-bc_req(Pid, {Op,Enc,M,F,A},MaybeConvert) ->
+bc_req(Pid, Req0, MaybeConvert) ->
case net_kernel:dflag_unicode_io(Pid) of
true ->
- {false,{Op,Enc,M,F,A}};
+ %% The most common case. A modern i/o server.
+ {false,Req0};
false ->
- {MaybeConvert,{Op,M,F,A}}
- end;
-bc_req(Pid, {Op,Enc,P,M,F,A},MaybeConvert) ->
- case net_kernel:dflag_unicode_io(Pid) of
- true ->
- {false,{Op,Enc,P,M,F,A}};
- false ->
- {MaybeConvert,{Op,P,M,F,A}}
- end;
-bc_req(Pid,{Op,Enc},MaybeConvert) ->
- case net_kernel:dflag_unicode_io(Pid) of
- true ->
- {false,{Op, Enc}};
- false ->
- {MaybeConvert,Op}
+ %% Backward compatibility only. Unlikely to ever happen.
+ case tuple_to_list(Req0) of
+ [Op,_Enc] ->
+ {MaybeConvert,Op};
+ [Op,_Enc|T] ->
+ Req = list_to_tuple([Op|T]),
+ {MaybeConvert,Req}
+ end
end.
io_request(Pid, {write,Term}) ->
diff --git a/lib/stdlib/src/otp_internal.erl b/lib/stdlib/src/otp_internal.erl
index 90ef364d1a..166eb3cef2 100644
--- a/lib/stdlib/src/otp_internal.erl
+++ b/lib/stdlib/src/otp_internal.erl
@@ -639,6 +639,12 @@ obsolete_1(httpd_conf, is_file, 1) ->
obsolete_1(httpd_conf, make_integer, 1) ->
{deprecated, "deprecated; use erlang:list_to_integer/1 instead"};
+%% Added in OTP 19.
+
+obsolete_1(random, _, _) ->
+ {deprecated, "the 'random' module is deprecated; "
+ "use the 'rand' module instead"};
+
obsolete_1(_, _, _) ->
no.
diff --git a/lib/stdlib/src/rand.erl b/lib/stdlib/src/rand.erl
index 8e8d0bc801..dc060e82d9 100644
--- a/lib/stdlib/src/rand.erl
+++ b/lib/stdlib/src/rand.erl
@@ -63,7 +63,7 @@
%% Return algorithm and seed so that RNG state can be recreated with seed/1
-spec export_seed() -> undefined | export_state().
export_seed() ->
- case seed_get() of
+ case get(?SEED_DICT) of
{#{type:=Alg}, Seed} -> {Alg, Seed};
_ -> undefined
end.
diff --git a/lib/stdlib/src/random.erl b/lib/stdlib/src/random.erl
index 8b67cde56c..8b639dd0a7 100644
--- a/lib/stdlib/src/random.erl
+++ b/lib/stdlib/src/random.erl
@@ -18,6 +18,7 @@
%% %CopyrightEnd%
%%
-module(random).
+-deprecated(module).
%% Reasonable random number generator.
%% The method is attributed to B. A. Wichmann and I. D. Hill
diff --git a/lib/stdlib/src/shell.erl b/lib/stdlib/src/shell.erl
index f215a66812..ce1d9eb0ff 100644
--- a/lib/stdlib/src/shell.erl
+++ b/lib/stdlib/src/shell.erl
@@ -999,12 +999,7 @@ local_func(rl, [A], Bs0, _Shell, RT, Lf, Ef) ->
{value,list_records(record_defs(RT, listify(Recs))),Bs};
local_func(rp, [A], Bs0, _Shell, RT, Lf, Ef) ->
{[V],Bs} = expr_list([A], Bs0, Lf, Ef),
- Cs = io_lib_pretty:print(V, ([{column, 1},
- {line_length, columns()},
- {depth, -1},
- {max_chars, ?CHAR_MAX},
- {record_print_fun, record_print_fun(RT)}]
- ++ enc())),
+ Cs = pp(V, _Column=1, _Depth=-1, RT),
io:requests([{put_chars, unicode, Cs}, nl]),
{value,ok,Bs};
local_func(rr, [A], Bs0, _Shell, RT, Lf, Ef) ->
@@ -1397,9 +1392,9 @@ get_history_and_results() ->
{History, erlang:min(Results, History)}.
pp(V, I, RT) ->
- pp(V, I, RT, enc()).
+ pp(V, I, _Depth=?LINEMAX, RT).
-pp(V, I, RT, Enc) ->
+pp(V, I, D, RT) ->
Strings =
case application:get_env(stdlib, shell_strings) of
{ok, false} ->
@@ -1408,10 +1403,10 @@ pp(V, I, RT, Enc) ->
true
end,
io_lib_pretty:print(V, ([{column, I}, {line_length, columns()},
- {depth, ?LINEMAX}, {max_chars, ?CHAR_MAX},
+ {depth, D}, {max_chars, ?CHAR_MAX},
{strings, Strings},
{record_print_fun, record_print_fun(RT)}]
- ++ Enc)).
+ ++ enc())).
columns() ->
case io:columns() of
diff --git a/lib/stdlib/test/base64_SUITE.erl b/lib/stdlib/test/base64_SUITE.erl
index 75eebba6c6..f750145ef0 100644
--- a/lib/stdlib/test/base64_SUITE.erl
+++ b/lib/stdlib/test/base64_SUITE.erl
@@ -340,7 +340,7 @@ interleaved_ws_roundtrip_1([], Base64List, Bin, List) ->
random_byte_list(0, Acc) ->
Acc;
random_byte_list(N, Acc) ->
- random_byte_list(N-1, [random:uniform(255)|Acc]).
+ random_byte_list(N-1, [rand:uniform(255)|Acc]).
make_big_binary(N) ->
list_to_binary(mbb(N, [])).
diff --git a/lib/stdlib/test/binary_module_SUITE.erl b/lib/stdlib/test/binary_module_SUITE.erl
index 70c946bdb9..8a2df2bf85 100644
--- a/lib/stdlib/test/binary_module_SUITE.erl
+++ b/lib/stdlib/test/binary_module_SUITE.erl
@@ -536,6 +536,12 @@ do_interesting(Module) ->
?line [<<3>>,<<6>>] = Module:split(<<1,2,3,4,5,6,7,8>>,
[<<1>>,<<2>>,<<4>>,<<5>>,<<7>>,<<8>>],
[global,trim_all]),
+ [<<>>] = binary:split(<<>>, <<",">>, []),
+ [] = binary:split(<<>>, <<",">>, [trim]),
+ [] = binary:split(<<>>, <<",">>, [trim_all]),
+ [] = binary:split(<<>>, <<",">>, [global,trim]),
+ [] = binary:split(<<>>, <<",">>, [global,trim_all]),
+
?line badarg = ?MASK_ERROR(
Module:replace(<<1,2,3,4,5,6,7,8>>,
[<<4,5>>,<<7>>,<<8>>],<<99>>,
@@ -710,7 +716,7 @@ do_interesting(Module) ->
encode_decode(doc) ->
["test binary:encode_unsigned/1,2 and binary:decode_unsigned/1,2"];
encode_decode(Config) when is_list(Config) ->
- ?line random:seed({1271,769940,559934}),
+ rand:seed(exsplus, {1271,769940,559934}),
?line ok = encode_decode_loop({1,200},1000), % Need to be long enough
% to create offheap binaries
ok.
@@ -817,7 +823,7 @@ copy(Config) when is_list(Config) ->
?line badarg = ?MASK_ERROR(binary:copy(<<1,2,3>>,
16#FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)),
?line <<>> = binary:copy(<<>>,10000),
- ?line random:seed({1271,769940,559934}),
+ rand:seed(exsplus, {1271,769940,559934}),
?line ok = random_copy(3000),
?line erts_debug:set_internal_state(available_internal_state,true),
?line io:format("oldlimit: ~p~n",
@@ -855,7 +861,7 @@ random_copy(0) ->
ok;
random_copy(N) ->
Str = random_string({0,N}),
- Num = random:uniform(N div 10+1),
+ Num = rand:uniform(N div 10+1),
A = ?MASK_ERROR(binary:copy(Str,Num)),
B = ?MASK_ERROR(binref:copy(Str,Num)),
C = ?MASK_ERROR(binary:copy(make_unaligned(Str),Num)),
@@ -896,7 +902,7 @@ bin_to_list(Config) when is_list(Config) ->
?line [5] = lists:nthtail(byte_size(X)-1,LX),
?line [0,5] = lists:nthtail(byte_size(X)-2,LX),
?line [0,5] = lists:nthtail(byte_size(Y)-2,LY),
- ?line random:seed({1271,769940,559934}),
+ rand:seed(exsplus, {1271,769940,559934}),
?line ok = random_bin_to_list(5000),
ok.
@@ -963,7 +969,7 @@ parts(Config) when is_list(Config) ->
?line badarg = ?MASK_ERROR(binary:part(Simple,{-1,0})),
?line badarg = ?MASK_ERROR(binary:part(Simple,{7,2})),
?line <<8>> = binary:part(Simple,{7,1}),
- ?line random:seed({1271,769940,559934}),
+ rand:seed(exsplus, {1271,769940,559934}),
?line random_parts(5000),
ok.
@@ -987,15 +993,15 @@ random_parts(N) ->
random_parts(0,_) ->
[];
random_parts(X,N) ->
- Pos = random:uniform(N),
- Len = random:uniform((Pos * 12) div 10),
+ Pos = rand:uniform(N),
+ Len = rand:uniform((Pos * 12) div 10),
[{Pos,Len} | random_parts(X-1,N)].
random_ref_comp(doc) ->
["Test pseudorandomly generated cases against reference imlementation"];
random_ref_comp(Config) when is_list(Config) ->
put(success_counter,0),
- random:seed({1271,769940,559934}),
+ rand:seed(exsplus, {1271,769940,559934}),
Nr = {1,40},
Hr = {30,1000},
I1 = 1500,
@@ -1025,7 +1031,7 @@ random_ref_sr_comp(doc) ->
["Test pseudorandomly generated cases against reference imlementation of split and replace"];
random_ref_sr_comp(Config) when is_list(Config) ->
put(success_counter,0),
- random:seed({1271,769940,559934}),
+ rand:seed(exsplus, {1271,769940,559934}),
Nr = {1,40},
Hr = {30,1000},
I1 = 1500,
@@ -1043,7 +1049,7 @@ random_ref_fla_comp(doc) ->
["Test pseudorandomly generated cases against reference imlementation of split and replace"];
random_ref_fla_comp(Config) when is_list(Config) ->
?line put(success_counter,0),
- ?line random:seed({1271,769940,559934}),
+ rand:seed(exsplus, {1271,769940,559934}),
?line do_random_first_comp(5000,{1,1000}),
?line do_random_last_comp(5000,{1,1000}),
?line do_random_at_comp(5000,{1,1000}),
@@ -1377,24 +1383,24 @@ one_random(N) ->
random_number({Min,Max}) -> % Min and Max are *length* of number in
% decimal positions
- X = random:uniform(Max - Min + 1) + Min - 1,
- list_to_integer([one_random_number(random:uniform(10)) || _ <- lists:seq(1,X)]).
+ X = rand:uniform(Max - Min + 1) + Min - 1,
+ list_to_integer([one_random_number(rand:uniform(10)) || _ <- lists:seq(1,X)]).
random_length({Min,Max}) ->
- random:uniform(Max - Min + 1) + Min - 1.
+ rand:uniform(Max - Min + 1) + Min - 1.
random_string({Min,Max}) ->
- X = random:uniform(Max - Min + 1) + Min - 1,
- list_to_binary([one_random(random:uniform(68)) || _ <- lists:seq(1,X)]).
+ X = rand:uniform(Max - Min + 1) + Min - 1,
+ list_to_binary([one_random(rand:uniform(68)) || _ <- lists:seq(1,X)]).
random_substring({Min,Max},Hay) ->
- X = random:uniform(Max - Min + 1) + Min - 1,
+ X = rand:uniform(Max - Min + 1) + Min - 1,
Y = byte_size(Hay),
Z = if
X > Y -> Y;
true -> X
end,
PMax = Y - Z,
- Pos = random:uniform(PMax + 1) - 1,
+ Pos = rand:uniform(PMax + 1) - 1,
<<_:Pos/binary,Res:Z/binary,_/binary>> = Hay,
Res.
diff --git a/lib/stdlib/test/dict_SUITE.erl b/lib/stdlib/test/dict_SUITE.erl
index 648154ebbe..aff73b176d 100644
--- a/lib/stdlib/test/dict_SUITE.erl
+++ b/lib/stdlib/test/dict_SUITE.erl
@@ -108,7 +108,7 @@ iterate_1(M) ->
M(empty, []).
iterate_2(M) ->
- random:seed(1, 2, 42),
+ rand:seed(exsplus, {1,2,42}),
iter_tree(M, 1000).
iter_tree(_M, 0) ->
@@ -117,7 +117,7 @@ iter_tree(M, N) ->
L = [{I, I} || I <- lists:seq(1, N)],
T = M(from_list, L),
L = lists:reverse(iterate_tree(M, T)),
- R = random:uniform(N),
+ R = rand:uniform(N),
KV = lists:reverse(iterate_tree_from(M, R, T)),
KV = [P || P={K,_} <- L, K >= R],
iter_tree(M, N-1).
@@ -156,7 +156,7 @@ test_all(Tester) ->
spawn_tester(M, Tester) ->
Parent = self(),
spawn_link(fun() ->
- random:seed(1, 2, 42),
+ rand:seed(exsplus, {1,2,42}),
S = Tester(M),
Res = {M(size, S),lists:sort(M(to_list, S))},
Parent ! {result,self(),Res}
@@ -194,12 +194,12 @@ rnd_list_1(0, Acc) ->
Acc;
rnd_list_1(N, Acc) ->
Key = atomic_rnd_term(),
- Value = random:uniform(100),
+ Value = rand:uniform(100),
rnd_list_1(N-1, [{Key,Value}|Acc]).
atomic_rnd_term() ->
- case random:uniform(3) of
- 1 -> list_to_atom(integer_to_list($\s+random:uniform(94))++"rnd");
- 2 -> random:uniform();
- 3 -> random:uniform(50)-37
+ case rand:uniform(3) of
+ 1 -> list_to_atom(integer_to_list($\s+rand:uniform(94))++"rnd");
+ 2 -> rand:uniform();
+ 3 -> rand:uniform(50)-37
end.
diff --git a/lib/stdlib/test/epp_SUITE.erl b/lib/stdlib/test/epp_SUITE.erl
index 199d2f193d..4c007e76ad 100644
--- a/lib/stdlib/test/epp_SUITE.erl
+++ b/lib/stdlib/test/epp_SUITE.erl
@@ -27,7 +27,7 @@
pmod/1, not_circular/1, skip_header/1, otp_6277/1, otp_7702/1,
otp_8130/1, overload_mac/1, otp_8388/1, otp_8470/1, otp_8503/1,
otp_8562/1, otp_8665/1, otp_8911/1, otp_10302/1, otp_10820/1,
- otp_11728/1, encoding/1]).
+ otp_11728/1, encoding/1, extends/1]).
-export([epp_parse_erl_form/2]).
@@ -70,7 +70,7 @@ all() ->
not_circular, skip_header, otp_6277, otp_7702, otp_8130,
overload_mac, otp_8388, otp_8470, otp_8503, otp_8562,
otp_8665, otp_8911, otp_10302, otp_10820, otp_11728,
- encoding].
+ encoding, extends].
groups() ->
[{upcase_mac, [], [upcase_mac_1, upcase_mac_2]},
@@ -621,6 +621,10 @@ otp_8130(Config) when is_list(Config) ->
" 2 end,\n"
" 7),\n"
" {2,7} =\n"
+ " ?M1(begin 1 = fun _Name () -> 1 end(),\n"
+ " 2 end,\n"
+ " 7),\n"
+ " {2,7} =\n"
" ?M1(begin 1 = fun t0/0(),\n"
" 2 end,\n"
" 7),\n"
@@ -645,6 +649,9 @@ otp_8130(Config) when is_list(Config) ->
" ?M1(begin yes = try 1 of 1 -> yes after foo end,\n"
" 2 end,\n"
" 7),\n"
+ " {[42],7} =\n"
+ " ?M1([42],\n"
+ " 7),\n"
"ok.\n">>,
ok},
@@ -728,11 +735,16 @@ otp_8130(Config) when is_list(Config) ->
{errors,[{{2,2},epp,{include,lib,"$apa/foo.hrl"}}],[]}},
- {otp_8130_c9,
+ {otp_8130_c9a,
<<"-define(S, ?S).\n"
"t() -> ?S.\n">>,
{errors,[{{2,9},epp,{circular,'S', none}}],[]}},
+ {otp_8130_c9b,
+ <<"-define(S(), ?S()).\n"
+ "t() -> ?S().\n">>,
+ {errors,[{{2,9},epp,{circular,'S', 0}}],[]}},
+
{otp_8130_c10,
<<"\n-file.">>,
{errors,[{{2,2},epp,{bad,file}}],[]}},
@@ -799,6 +811,10 @@ otp_8130(Config) when is_list(Config) ->
<<"\n-include(\"no such file.erl\").\n">>,
{errors,[{{2,2},epp,{include,file,"no such file.erl"}}],[]}},
+ {otp_8130_c25,
+ <<"\n-define(A.\n">>,
+ {errors,[{{2,2},epp,{bad,define}}],[]}},
+
{otp_8130_7,
<<"-record(b, {b}).\n"
"-define(A, {{a,#b.b.\n"
@@ -1476,6 +1492,20 @@ encoding(Config) when is_list(Config) ->
epp_parse_file(ErlFile, [{default_encoding,utf8},extra]),
ok.
+extends(Config) ->
+ Cs = [{extends_c1,
+ <<"-extends(some.other.module).\n">>,
+ {errors,[{1,erl_parse,["syntax error before: ","'.'"]}],[]}}],
+ [] = compile(Config, Cs),
+
+ Ts = [{extends_1,
+ <<"-extends(some_other_module).\n"
+ "t() -> {?BASE_MODULE,?BASE_MODULE_STRING}.\n">>,
+ {some_other_module,"some_other_module"}}],
+
+ [] = run(Config, Ts),
+ ok.
+
check(Config, Tests) ->
eval_tests(Config, fun check_test/2, Tests).
@@ -1504,15 +1534,17 @@ eval_tests(Config, Fun, Tests) ->
check_test(Config, Test) ->
Filename = "epp_test.erl",
- ?line PrivDir = ?config(priv_dir, Config),
- ?line File = filename:join(PrivDir, Filename),
- ?line ok = file:write_file(File, Test),
- ?line case epp:parse_file(File, [PrivDir], []) of
- {ok,Forms} ->
- [E || E={error,_} <- Forms];
- {error,Error} ->
- Error
- end.
+ PrivDir = ?config(priv_dir, Config),
+ File = filename:join(PrivDir, Filename),
+ ok = file:write_file(File, Test),
+ case epp:parse_file(File, [PrivDir], []) of
+ {ok,Forms} ->
+ Errors = [E || E={error,_} <- Forms],
+ call_format_error([E || {error,E} <- Errors]),
+ Errors;
+ {error,Error} ->
+ Error
+ end.
compile_test(Config, Test0) ->
Test = [<<"-module(epp_test). -compile(export_all). ">>, Test0],
diff --git a/lib/stdlib/test/erl_lint_SUITE.erl b/lib/stdlib/test/erl_lint_SUITE.erl
index 6c07dc1ec6..3c746a13d7 100644
--- a/lib/stdlib/test/erl_lint_SUITE.erl
+++ b/lib/stdlib/test/erl_lint_SUITE.erl
@@ -65,7 +65,7 @@
too_many_arguments/1,
basic_errors/1,bin_syntax_errors/1,
predef/1,
- maps/1,maps_type/1,otp_11851/1
+ maps/1,maps_type/1,otp_11851/1,otp_11879/1
]).
% Default timetrap timeout (set in init_per_testcase).
@@ -94,7 +94,7 @@ all() ->
bif_clash, behaviour_basic, behaviour_multiple, otp_11861,
otp_7550, otp_8051, format_warn, {group, on_load},
too_many_arguments, basic_errors, bin_syntax_errors, predef,
- maps, maps_type, otp_11851].
+ maps, maps_type, otp_11851, otp_11879].
groups() ->
[{unused_vars_warn, [],
@@ -1296,12 +1296,16 @@ unsized_binary_in_bin_gen_pattern(Config) when is_list(Config) ->
Ts = [{unsized_binary_in_bin_gen_pattern,
<<"t({bc,binary,Bin}) ->
<< <<X,Tail/binary>> || <<X,Tail/binary>> <= Bin >>;
+ t({bc,bytes,Bin}) ->
+ << <<X,Tail/binary>> || <<X,Tail/bytes>> <= Bin >>;
t({bc,bits,Bin}) ->
<< <<X,Tail/bits>> || <<X,Tail/bits>> <= Bin >>;
t({bc,bitstring,Bin}) ->
<< <<X,Tail/bits>> || <<X,Tail/bitstring>> <= Bin >>;
t({lc,binary,Bin}) ->
[ {X,Tail} || <<X,Tail/binary>> <= Bin ];
+ t({lc,bytes,Bin}) ->
+ [ {X,Tail} || <<X,Tail/bytes>> <= Bin ];
t({lc,bits,Bin}) ->
[ {X,Tail} || <<X,Tail/bits>> <= Bin ];
t({lc,bitstring,Bin}) ->
@@ -1313,7 +1317,9 @@ unsized_binary_in_bin_gen_pattern(Config) when is_list(Config) ->
{6,erl_lint,unsized_binary_in_bin_gen_pattern},
{8,erl_lint,unsized_binary_in_bin_gen_pattern},
{10,erl_lint,unsized_binary_in_bin_gen_pattern},
- {12,erl_lint,unsized_binary_in_bin_gen_pattern}],
+ {12,erl_lint,unsized_binary_in_bin_gen_pattern},
+ {14,erl_lint,unsized_binary_in_bin_gen_pattern},
+ {16,erl_lint,unsized_binary_in_bin_gen_pattern}],
[]}}],
[] = run(Config, Ts),
ok.
@@ -3604,7 +3610,10 @@ bin_syntax_errors(Config) ->
t(<<X/unit:8>>) -> X;
t(<<X:7/float>>) -> X;
t(<< <<_:8>> >>) -> ok;
- t(<<(x ! y):8/integer>>) -> ok.
+ t(<<(x ! y):8/integer>>) -> ok;
+ t(X) ->
+ {<<X/binary-integer>>,<<X/signed-unsigned-integer>>,
+ <<X/little-big>>,<<X/unit:4-unit:8>>}.
">>,
[],
{error,[{1,erl_lint,illegal_bitsize},
@@ -3613,7 +3622,12 @@ bin_syntax_errors(Config) ->
{4,erl_lint,{undefined_bittype,bad_type}},
{5,erl_lint,bittype_unit},
{7,erl_lint,illegal_pattern},
- {8,erl_lint,illegal_pattern}],
+ {8,erl_lint,illegal_pattern},
+ {10,erl_lint,{bittype_mismatch,integer,binary,"type"}},
+ {10,erl_lint,{bittype_mismatch,unsigned,signed,"sign"}},
+ {11,erl_lint,{bittype_mismatch,8,4,"unit"}},
+ {11,erl_lint,{bittype_mismatch,big,little,"endianness"}}
+ ],
[{6,erl_lint,{bad_bitsize,"float"}}]}}
],
[] = run(Config, Ts),
@@ -3835,6 +3849,29 @@ otp_11851(Config) when is_list(Config) ->
[] = run(Config, Ts),
ok.
+otp_11879(doc) ->
+ "OTP-11879: The -spec f/a :: (As) -> B; syntax removed, "
+ "and is_subtype/2 deprecated";
+otp_11879(_Config) ->
+ Fs = [{attribute,0,file,{"file.erl",0}},
+ {attribute,0,module,m},
+ {attribute,1,spec,
+ {{f,1},
+ [{type,2,'fun',[{type,3,product,[{var,4,'V1'},
+ {var,5,'V1'}]},
+ {type,6,integer,[]}]}]}},
+ {attribute,20,callback,
+ {{cb,21},
+ [{type,22,'fun',[{type,23,product,[{var,24,'V1'},
+ {var,25,'V1'}]},
+ {type,6,integer,[]}]}]}}],
+ {error,[{"file.erl",
+ [{1,erl_lint,{spec_fun_undefined,{f,1}}},
+ {2,erl_lint,spec_wrong_arity},
+ {22,erl_lint,callback_wrong_arity}]}],
+ []} = compile:forms(Fs, [return,report]),
+ ok.
+
run(Config, Tests) ->
F = fun({N,P,Ws,E}, BadL) ->
case catch run_test(Config, P, Ws) of
@@ -3886,22 +3923,35 @@ run_test2(Conf, Test, Warnings0) ->
%% is no reason to produce an output file since we are only
%% interested in the errors and warnings.
- %% Print warnings, call erl_lint:format_error/1.
+ %% Print warnings, call erl_lint:format_error/1. (But note that
+ %% the compiler will ignore failing calls to erl_lint:format_error/1.)
compile:file(File, [binary,report|Opts]),
case compile:file(File, [binary|Opts]) of
- {ok, _M, Code, Ws} when is_binary(Code) -> warnings(File, Ws);
- {error, [{File,Es}], []} -> {errors, Es, []};
- {error, [{File,Es}], [{File,Ws}]} -> {error, Es, Ws};
- {error, [{File,Es1},{File,Es2}], []} -> {errors2, Es1, Es2}
+ {ok, _M, Code, Ws} when is_binary(Code) ->
+ warnings(File, Ws);
+ {error, [{File,Es}], []} ->
+ {errors, call_format_error(Es), []};
+ {error, [{File,Es}], [{File,Ws}]} ->
+ {error, call_format_error(Es), call_format_error(Ws)};
+ {error, [{File,Es1},{File,Es2}], []} ->
+ {errors2, Es1, Es2}
end.
warnings(File, Ws) ->
case lists:append([W || {F, W} <- Ws, F =:= File]) of
- [] -> [];
- L -> {warnings, L}
+ [] ->
+ [];
+ L ->
+ {warnings, call_format_error(L)}
end.
+call_format_error(L) ->
+ %% Smoke test of format_error/1 to make sure that no crashes
+ %% slip through.
+ _ = [Mod:format_error(Term) || {_,Mod,Term} <- L],
+ L.
+
fail() ->
io:format("failed~n"),
?t:fail().
diff --git a/lib/stdlib/test/erl_pp_SUITE.erl b/lib/stdlib/test/erl_pp_SUITE.erl
index 9bb193d865..8a128b3815 100644
--- a/lib/stdlib/test/erl_pp_SUITE.erl
+++ b/lib/stdlib/test/erl_pp_SUITE.erl
@@ -876,6 +876,9 @@ type_examples() ->
{ex30,<<"-type t99() ::"
"{t2(),'\\'t::4'(),t5(),t6(),t7(),t8(),t10(),t14(),"
"t15(),t20(),t21(), t22(),t25()}. ">>},
+ %% Writing constraints as is_subtype(V, T) is not supported since
+ %% Erlang/OTP 19.0, but as long as the parser recognizes the
+ %% is_subtype(V, T) syntax, we need a few examples of the syntax.
{ex31,<<"-spec t1(FooBar :: t99()) -> t99();"
"(t2()) -> t2();"
"('\\'t::4'()) -> '\\'t::4'() when is_subtype('\\'t::4'(), t24);"
@@ -962,6 +965,9 @@ maps_syntax(Config) when is_list(Config) ->
"-compile(export_all).\n"
"-type t1() :: map().\n"
"-type t2() :: #{ atom() => integer(), atom() => float() }.\n"
+ "-type u() :: #{a => (I :: integer()) | (A :: atom()),\n"
+ " (X :: atom()) | (Y :: atom()) =>\n"
+ " (I :: integer()) | (A :: atom())}.\n"
"-spec f1(t1()) -> 'true'.\n"
"f1(M) when is_map(M) -> true.\n"
"-spec f2(t2()) -> integer().\n"
@@ -997,18 +1003,10 @@ otp_8567(Config) when is_list(Config) ->
"t() ->\n"
" 3.\n"
"\n"
- "-spec(t1/1 :: (ot()) -> ot1()).\n"
- "t1(A) ->\n"
- " A.\n"
- "\n"
"-spec(t2 (ot()) -> ot1()).\n"
"t2(A) ->\n"
" A.\n"
"\n"
- "-spec(otp_8567:t3/1 :: (ot()) -> ot1()).\n"
- "t3(A) ->\n"
- " A.\n"
- "\n"
"-spec(otp_8567:t4 (ot()) -> ot1()).\n"
"t4(A) ->\n"
" A.\n">>,
diff --git a/lib/stdlib/test/ets_SUITE.erl b/lib/stdlib/test/ets_SUITE.erl
index 1b80f555d7..3e63d19213 100644
--- a/lib/stdlib/test/ets_SUITE.erl
+++ b/lib/stdlib/test/ets_SUITE.erl
@@ -112,9 +112,8 @@
-define(m(A,B), ?line assert_eq(A,B)).
init_per_testcase(Case, Config) ->
- Seed = {S1,S2,S3} = random:seed0(), %now(),
- random:seed(S1,S2,S3),
- io:format("*** SEED: ~p ***\n", [Seed]),
+ rand:seed(exsplus),
+ io:format("*** SEED: ~p ***\n", [rand:export_seed()]),
start_spawn_logger(),
wait_for_test_procs(), %% Ensure previous case cleaned up
Dog=test_server:timetrap(test_server:minutes(20)),
@@ -1330,7 +1329,7 @@ drop_match() ->
ets_match(Tab,Expr) ->
- case random:uniform(2) of
+ case rand:uniform(2) of
1 ->
ets:match(Tab,Expr);
_ ->
@@ -1339,14 +1338,14 @@ ets_match(Tab,Expr) ->
match_chunked(Tab,Expr) ->
match_chunked_collect(ets:match(Tab,Expr,
- random:uniform(1999) + 1)).
+ rand:uniform(1999) + 1)).
match_chunked_collect('$end_of_table') ->
[];
match_chunked_collect({Results, Continuation}) ->
Results ++ match_chunked_collect(ets:match(Continuation)).
ets_match_object(Tab,Expr) ->
- case random:uniform(2) of
+ case rand:uniform(2) of
1 ->
ets:match_object(Tab,Expr);
_ ->
@@ -1355,7 +1354,7 @@ ets_match_object(Tab,Expr) ->
match_object_chunked(Tab,Expr) ->
match_object_chunked_collect(ets:match_object(Tab,Expr,
- random:uniform(1999) + 1)).
+ rand:uniform(1999) + 1)).
match_object_chunked_collect('$end_of_table') ->
[];
match_object_chunked_collect({Results, Continuation}) ->
@@ -1367,19 +1366,15 @@ random_test() ->
?line ReadDir = get(where_to_read),
?line WriteDir = get(where_to_write),
?line (catch file:make_dir(WriteDir)),
- ?line Seed = case file:consult(filename:join([ReadDir,
- "preset_random_seed.txt"])) of
- {ok,[X]} ->
- X;
- _ ->
- {A,B,C} = erlang:timestamp(),
- random:seed(A,B,C),
- get(random_seed)
- end,
- put(random_seed,Seed),
- ?line {ok, F} = file:open(filename:join([WriteDir,
- "last_random_seed.txt"]),
- [write]),
+ case file:consult(filename:join([ReadDir,"preset_random_seed.txt"])) of
+ {ok,[X]} ->
+ rand:seed(X);
+ _ ->
+ rand:seed(exsplus)
+ end,
+ Seed = rand:export_seed(),
+ {ok,F} = file:open(filename:join([WriteDir,"last_random_seed.txt"]),
+ [write]),
io:format(F,"~p. ~n",[Seed]),
file:close(F),
io:format("Random seed ~p written to ~s, copy to ~s to rerun with "
@@ -1401,7 +1396,7 @@ do_random_test() ->
end, 5000),
?line io:format("~nData inserted~n"),
?line do_n_times(fun() ->
- ?line I = random:uniform(25),
+ I = rand:uniform(25),
?line Key = create_random_string(I) ++ '_',
?line L1 = ets_match_object(OrdSet,{Key,'_'}),
?line L2 = lists:sort(ets_match_object(Set,{Key,'_'})),
@@ -1961,7 +1956,7 @@ evil_update_counter(Config) when is_list(Config) ->
gb_sets:module_info(),
math:module_info(),
ordsets:module_info(),
- random:module_info(),
+ rand:module_info(),
repeat_for_opts(evil_update_counter_do).
@@ -1995,7 +1990,7 @@ evil_counter(I,Opts) ->
1 -> 16#12345678FFFFFFFF;
2 -> 16#7777777777FFFFFFFF863648726743
end,
- Start = Start0 + random:uniform(100000),
+ Start = Start0 + rand:uniform(100000),
ets:insert(T, {dracula,Start}),
Iter = 40000,
End = Start + Iter,
@@ -4645,11 +4640,11 @@ create_random_string(0) ->
[];
create_random_string(OfLength) ->
- C = case random:uniform(2) of
+ C = case rand:uniform(2) of
1 ->
- (random:uniform($Z - $A + 1) - 1) + $A;
+ (rand:uniform($Z - $A + 1) - 1) + $A;
_ ->
- (random:uniform($z - $a + 1) - 1) + $a
+ (rand:uniform($z - $a + 1) - 1) + $a
end,
[C | create_random_string(OfLength - 1)].
@@ -4660,7 +4655,7 @@ create_random_tuple(OfLength) ->
end,create_random_string(OfLength))).
create_partly_bound_tuple(OfLength) ->
- case random:uniform(2) of
+ case rand:uniform(2) of
1 ->
create_partly_bound_tuple1(OfLength);
_ ->
@@ -4669,14 +4664,14 @@ create_partly_bound_tuple(OfLength) ->
create_partly_bound_tuple1(OfLength) ->
T0 = create_random_tuple(OfLength),
- I = random:uniform(OfLength),
+ I = rand:uniform(OfLength),
setelement(I,T0,'$1').
set_n_random_elements(T0,0,_,_) ->
T0;
set_n_random_elements(T0,N,OfLength,GenFun) ->
- I = random:uniform(OfLength),
+ I = rand:uniform(OfLength),
What = GenFun(I),
case element(I,T0) of
What ->
@@ -4690,12 +4685,12 @@ make_dollar_atom(I) ->
list_to_atom([$$] ++ integer_to_list(I)).
create_partly_bound_tuple2(OfLength) ->
T0 = create_random_tuple(OfLength),
- I = random:uniform(OfLength - 1),
+ I = rand:uniform(OfLength - 1),
set_n_random_elements(T0,I,OfLength,fun make_dollar_atom/1).
create_partly_bound_tuple3(OfLength) ->
T0 = create_random_tuple(OfLength),
- I = random:uniform(OfLength - 1),
+ I = rand:uniform(OfLength - 1),
set_n_random_elements(T0,I,OfLength,fun(_) -> '_' end).
do_n_times(_,0) ->
@@ -5058,11 +5053,12 @@ meta_wb_do(Opts) ->
io:format("Colliding names = ~p\n",[Names]),
F = fun(0,_,_) -> ok;
- (N,Tabs,Me) -> Name1 = lists:nth(random:uniform(Len),Names),
- Name2 = lists:nth(random:uniform(Len),Names),
- Op = element(random:uniform(3),OpFuns),
- NTabs = Op(Name1, Name2, Tabs, Opts),
- Me(N-1,NTabs,Me)
+ (N,Tabs,Me) ->
+ Name1 = lists:nth(rand:uniform(Len), Names),
+ Name2 = lists:nth(rand:uniform(Len), Names),
+ Op = element(rand:uniform(3),OpFuns),
+ NTabs = Op(Name1, Name2, Tabs, Opts),
+ Me(N-1, NTabs, Me)
end,
F(Len*100, [], F),
@@ -5328,7 +5324,7 @@ smp_insert(suite) -> [];
smp_insert(Config) when is_list(Config) ->
ets_new(smp_insert,[named_table,public,{write_concurrency,true}]),
InitF = fun(_) -> ok end,
- ExecF = fun(_) -> true = ets:insert(smp_insert,{random:uniform(10000)})
+ ExecF = fun(_) -> true = ets:insert(smp_insert,{rand:uniform(10000)})
end,
FiniF = fun(_) -> ok end,
run_workers(InitF,ExecF,FiniF,100000),
@@ -5579,10 +5575,10 @@ smp_select_delete(Config) when is_list(Config) ->
Zeros = erlang:make_tuple(Mod,0),
InitF = fun(_) -> Zeros end,
ExecF = fun(Diffs0) ->
- case random:uniform(20) of
+ case rand:uniform(20) of
1 ->
Mod = 17,
- Eq = random:uniform(Mod) - 1,
+ Eq = rand:uniform(Mod) - 1,
Deleted = ets:select_delete(T,
[{{'_', '$1'},
[{'=:=', {'rem', '$1', Mod}, Eq}],
@@ -5591,7 +5587,7 @@ smp_select_delete(Config) when is_list(Config) ->
element(Eq+1,Diffs0) - Deleted),
Diffs1;
_ ->
- Key = random:uniform(10000),
+ Key = rand:uniform(10000),
Eq = Key rem Mod,
?line case ets:insert_new(T,{Key,Key}) of
true ->
@@ -5795,7 +5791,7 @@ run_workers_do(InitF,ExecF,FiniF,Laps, Exclude) ->
N when (N > Exclude) -> N - Exclude
end,
io:format("smp starting ~p workers\n",[NumOfProcs]),
- Seeds = [{ProcN,random:uniform(9999)} || ProcN <- lists:seq(1,NumOfProcs)],
+ Seeds = [{ProcN,rand:uniform(9999)} || ProcN <- lists:seq(1,NumOfProcs)],
Parent = self(),
Pids = [my_spawn_link(fun()-> worker(Seed,InitF,ExecF,FiniF,Laps,Parent,NumOfProcs) end)
|| Seed <- Seeds],
@@ -5806,7 +5802,7 @@ run_workers_do(InitF,ExecF,FiniF,Laps, Exclude) ->
worker({ProcN,Seed}, InitF, ExecF, FiniF, Laps, Parent, NumOfProcs) ->
io:format("smp worker ~p, seed=~p~n",[self(),Seed]),
- random:seed(Seed,Seed,Seed),
+ rand:seed(exsplus, {Seed,Seed,Seed}),
State1 = InitF([ProcN, NumOfProcs]),
State2 = worker_loop(Laps, ExecF, State1),
Result = FiniF(State2),
diff --git a/lib/stdlib/test/ets_tough_SUITE.erl b/lib/stdlib/test/ets_tough_SUITE.erl
index c6f24fc670..8a7f2b1ec2 100644
--- a/lib/stdlib/test/ets_tough_SUITE.erl
+++ b/lib/stdlib/test/ets_tough_SUITE.erl
@@ -92,7 +92,7 @@ ex1_sub(Config) ->
ok.
prep(Config) ->
- random:seed(),
+ rand:seed(exsplus),
put(dump_ticket,none),
DumpDir = filename:join(?config(priv_dir,Config), "ets_tough"),
file:make_dir(DumpDir),
@@ -221,19 +221,19 @@ random_class() ->
random_element(Classes).
random_key() ->
- random:uniform(8).
+ rand:uniform(8).
random_value() ->
- case random:uniform(5) of
+ case rand:uniform(5) of
1 -> ok;
2 -> {data,random_key()};
3 -> {foo,bar,random_class()};
- 4 -> random:uniform(1000);
+ 4 -> rand:uniform(1000);
5 -> {recursive,random_value()}
end.
random_element(T) ->
- I = random:uniform(tuple_size(T)),
+ I = rand:uniform(tuple_size(T)),
element(I,T).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/lib/stdlib/test/filelib_SUITE.erl b/lib/stdlib/test/filelib_SUITE.erl
index 01b798faef..c39ff842ee 100644
--- a/lib/stdlib/test/filelib_SUITE.erl
+++ b/lib/stdlib/test/filelib_SUITE.erl
@@ -318,7 +318,7 @@ same_lists(Expected0, Actual0, BaseDir) ->
mkfiles([H|T], Dir) ->
Name = filename:join(Dir, H),
- Garbage = [31+random:uniform(95) || _ <- lists:seq(1, random:uniform(1024))],
+ Garbage = [31+rand:uniform(95) || _ <- lists:seq(1, rand:uniform(1024))],
file:write_file(Name, Garbage),
[Name|mkfiles(T, Dir)];
mkfiles([], _) -> [].
diff --git a/lib/stdlib/test/lists_SUITE.erl b/lib/stdlib/test/lists_SUITE.erl
index a0f7fd2744..bd68c93779 100644
--- a/lib/stdlib/test/lists_SUITE.erl
+++ b/lib/stdlib/test/lists_SUITE.erl
@@ -1677,8 +1677,7 @@ check_stab(L, U, S, US, SS) ->
%%% Element 3 in the tuple is the position of the tuple in the list.
biglist(N) ->
- {A, B, C} = get_seed(),
- random:seed(A, B, C),
+ rand:seed(exsplus),
biglist(N, []).
biglist(0, L) ->
@@ -1694,8 +1693,7 @@ biglist(N, L) ->
%%% No sequence number.
ubiglist(N) ->
- {A, B, C} = get_seed(),
- random:seed(A, B, C),
+ rand:seed(exsplus),
ubiglist(N, []).
ubiglist(0, L) ->
@@ -1719,8 +1717,7 @@ urandom_tuple(N, I) ->
%%% sequence number.
bigfunlist(N) ->
- {A, B, C} = get_seed(),
- random:seed(A, B, C),
+ rand:seed(exsplus),
bigfunlist_1(N).
bigfunlist_1(N) when N < 30000 -> % Now (R8) max 32000 different pids.
@@ -1754,21 +1751,13 @@ make_fun(Pid) ->
fun_pid(Fun) ->
erlang:fun_info(Fun, pid).
-get_seed() ->
- case random:seed() of
- undefined ->
- erlang:timestamp();
- Tuple ->
- Tuple
- end.
-
random_tuple(N, Seq) ->
R1 = randint(N),
R2 = randint(N),
{R1, R2, Seq}.
randint(N) ->
- trunc(random:uniform() * N).
+ trunc(rand:uniform() * N).
%% The first "duplicate" is kept.
no_dups([]) ->
@@ -1830,8 +1819,7 @@ sort_loop_1(Pid) ->
end.
sloop(N) ->
- {A, B, C} = get_seed(),
- random:seed(A, B, C),
+ rand:seed(exsplus),
sloop(N, #state{}).
sloop(N, S) ->
diff --git a/lib/stdlib/test/queue_SUITE.erl b/lib/stdlib/test/queue_SUITE.erl
index c965a8b218..5165ac3a3a 100644
--- a/lib/stdlib/test/queue_SUITE.erl
+++ b/lib/stdlib/test/queue_SUITE.erl
@@ -470,7 +470,7 @@ oops(suite) ->
oops(Config) when is_list(Config) ->
?line N = 3142,
?line Optab = optab(),
- ?line Seed0 = random:seed0(),
+ ?line Seed0 = rand:seed(exsplus, {1,2,4}),
?line {Is,Seed} = random_list(N, tuple_size(Optab), Seed0, []),
?line io:format("~p ", [Is]),
?line QA = queue:new(),
@@ -562,20 +562,20 @@ args([], _, Seed, R) ->
args([q|Ts], [Q|Qs]=Qss, Seed, R) ->
args(Ts, if Qs =:= [] -> Qss; true -> Qs end, Seed, [Q|R]);
args([l|Ts], Qs, Seed0, R) ->
- {N,Seed1} = random:uniform_s(17, Seed0),
+ {N,Seed1} = rand:uniform_s(17, Seed0),
{L,Seed} = random_list(N, 4711, Seed1, []),
args(Ts, Qs, Seed, [L|R]);
args([t|Ts], Qs, Seed0, R) ->
- {T,Seed} = random:uniform_s(4711, Seed0),
+ {T,Seed} = rand:uniform_s(4711, Seed0),
args(Ts, Qs, Seed, [T|R]);
args([n|Ts], Qs, Seed0, R) ->
- {N,Seed} = random:uniform_s(17, Seed0),
+ {N,Seed} = rand:uniform_s(17, Seed0),
args(Ts, Qs, Seed, [N|R]).
random_list(0, _, Seed, R) ->
{R,Seed};
random_list(N, M, Seed0, R) ->
- {X,Seed} = random:uniform_s(M, Seed0),
+ {X,Seed} = rand:uniform_s(M, Seed0),
random_list(N-1, M, Seed, [X|R]).
call(Func, As) ->
diff --git a/lib/stdlib/test/rand_SUITE.erl b/lib/stdlib/test/rand_SUITE.erl
index 111bf620de..03b5ce1a25 100644
--- a/lib/stdlib/test/rand_SUITE.erl
+++ b/lib/stdlib/test/rand_SUITE.erl
@@ -126,6 +126,9 @@ seed_1(Alg) ->
false = (S1 =:= rand:seed_s(Alg)),
%% Negative integers works
_ = rand:seed_s(Alg, {-1,-1,-1}),
+ %% Check that export_seed/1 returns 'undefined' if there is no seed
+ erase(rand_seed),
+ undefined = rand:export_seed(),
%% Other term do not work
{'EXIT', _} = (catch rand:seed_s(foobar, os:timestamp())),
diff --git a/lib/stdlib/test/random_iolist.erl b/lib/stdlib/test/random_iolist.erl
index 9a0f034e72..6da7da04de 100644
--- a/lib/stdlib/test/random_iolist.erl
+++ b/lib/stdlib/test/random_iolist.erl
@@ -36,7 +36,7 @@ run2(Iter,Fun1,Fun2) ->
compare2(Iter,Fun1,Fun2).
random_byte() ->
- random:uniform(256) - 1.
+ rand:uniform(256) - 1.
random_list(0,Acc) ->
Acc;
@@ -45,7 +45,7 @@ random_list(N,Acc) ->
random_binary(N) ->
B = list_to_binary(random_list(N,[])),
- case {random:uniform(2),size(B)} of
+ case {rand:uniform(2),size(B)} of
{2,M} when M > 1 ->
S = M-1,
<<_:3,C:S/binary,_:5>> = B,
@@ -57,7 +57,7 @@ random_list(N) ->
random_list(N,[]).
front() ->
- case random:uniform(10) of
+ case rand:uniform(10) of
10 ->
false;
_ ->
@@ -65,7 +65,7 @@ front() ->
end.
any_type() ->
- case random:uniform(10) of
+ case rand:uniform(10) of
1 ->
list;
2 ->
@@ -77,7 +77,7 @@ any_type() ->
end.
tail_type() ->
- case random:uniform(5) of
+ case rand:uniform(5) of
1 ->
list;
2 ->
@@ -90,9 +90,9 @@ random_length(N) ->
UpperLimit = 255,
case N of
M when M > UpperLimit ->
- random:uniform(UpperLimit+1) - 1;
+ rand:uniform(UpperLimit+1) - 1;
_ ->
- random:uniform(N+1) - 1
+ rand:uniform(N+1) - 1
end.
random_iolist(0,Acc) ->
@@ -139,7 +139,7 @@ random_iolist(N) ->
standard_seed() ->
- random:seed(1201,855653,380975).
+ rand:seed(exsplus, {1201,855653,380975}).
do_comp(List,F1,F2) ->
X = F1(List),
diff --git a/lib/stdlib/test/random_unicode_list.erl b/lib/stdlib/test/random_unicode_list.erl
index ecafe42318..3bc86a8430 100644
--- a/lib/stdlib/test/random_unicode_list.erl
+++ b/lib/stdlib/test/random_unicode_list.erl
@@ -85,7 +85,7 @@ int_to_utf32_little(I) ->
id(I) -> I.
random_char() ->
- case random:uniform(16#10FFFF+1) - 1 of
+ case rand:uniform(16#10FFFF+1) - 1 of
X when X >= 16#D800,
X =< 16#DFFF ->
random_char();
@@ -116,13 +116,13 @@ random_binary(N,Enc) ->
int_to(Enc,X)
end,
L)),
- case {random:uniform(3),size(B)} of
+ case {rand:uniform(3),size(B)} of
{2,M} when M > 1 ->
B2 = id(<<1:3,B/binary,1:5>>),
<<_:3,C:M/binary,_:5>> = B2,
C;
{3,M} when M > 1 ->
- X = random:uniform(M+1)-1,
+ X = rand:uniform(M+1)-1,
<<B1:X/binary,B2/binary>> = B,
[B1,B2];
_ ->
@@ -132,7 +132,7 @@ random_list(N) ->
random_list(N,[]).
front() ->
- case random:uniform(10) of
+ case rand:uniform(10) of
10 ->
false;
_ ->
@@ -140,7 +140,7 @@ front() ->
end.
any_type() ->
- case random:uniform(10) of
+ case rand:uniform(10) of
1 ->
list;
2 ->
@@ -152,7 +152,7 @@ any_type() ->
end.
tail_type() ->
- case random:uniform(5) of
+ case rand:uniform(5) of
1 ->
list;
2 ->
@@ -165,9 +165,9 @@ random_length(N) ->
UpperLimit = 255,
case N of
M when M > UpperLimit ->
- random:uniform(UpperLimit+1) - 1;
+ rand:uniform(UpperLimit+1) - 1;
_ ->
- random:uniform(N+1) - 1
+ rand:uniform(N+1) - 1
end.
random_unicode_list(0,Acc,_Enc) ->
@@ -214,7 +214,7 @@ random_unicode_list(N,Enc) ->
standard_seed() ->
- random:seed(1201,855653,380975).
+ rand:seed(exsplus, {1201,855653,380975}).
do_comp(List,F1,F2) ->
X = F1(List),
diff --git a/lib/stdlib/test/run_pcre_tests.erl b/lib/stdlib/test/run_pcre_tests.erl
index 1fdc777470..b7d1df39b8 100644
--- a/lib/stdlib/test/run_pcre_tests.erl
+++ b/lib/stdlib/test/run_pcre_tests.erl
@@ -1083,7 +1083,7 @@ dumponesplit(F,{RE,Line,O,TS}) ->
%% Generate replacement tests from indatafile,
%% you will need perl on the machine
gen_repl_test(OneFile) ->
- random:seed(1219,687731,62804),
+ rand:seed(exsplus, {1219,687731,62804}),
{ok,Bin} = file:read_file(OneFile),
Lines = splitfile(0,Bin,1),
Structured = stru(Lines),
@@ -1237,15 +1237,15 @@ btr(_) ->
ranchar() ->
- case random:uniform(10) of
+ case rand:uniform(10) of
9 -> $&;
10 -> <<"\\1">>;
N when N < 5 ->
- random:uniform($Z-$A)+$A-1;
+ rand:uniform($Z-$A)+$A-1;
M when M < 9 ->
- random:uniform($z-$a)+$a-1
+ rand:uniform($z-$a)+$a-1
end.
ranstring() ->
- iolist_to_binary([ranchar() || _ <- lists:duplicate(random:uniform(20),0) ]).
+ iolist_to_binary([ranchar() || _ <- lists:duplicate(rand:uniform(20),0) ]).
diff --git a/lib/stdlib/test/select_SUITE.erl b/lib/stdlib/test/select_SUITE.erl
index ead64ffc75..6796676179 100644
--- a/lib/stdlib/test/select_SUITE.erl
+++ b/lib/stdlib/test/select_SUITE.erl
@@ -212,11 +212,10 @@ init_random(Config) ->
{ok,[X]} ->
X;
_ ->
- {A,B,C} = erlang:timestamp(),
- random:seed(A,B,C),
- get(random_seed)
+ rand:seed(exsplus),
+ rand:export_seed()
end,
- put(random_seed,Seed),
+ rand:seed(Seed),
{ok, F} = file:open(filename:join([WriteDir, "last_random_seed2.txt"]),
[write]),
io:format(F,"~p. ~n",[Seed]),
@@ -224,11 +223,11 @@ init_random(Config) ->
ok.
create_random_key(N,Type) ->
- gen_key(random:uniform(N),Type).
+ gen_key(rand:uniform(N),Type).
create_pb_key(N,list) ->
- X = random:uniform(N),
- case random:uniform(4) of
+ X = rand:uniform(N),
+ case rand:uniform(4) of
3 -> {[X, X+1, '_'], fun([Z,Z1,P1]) ->
[Z,Z1,P1] =:= [X,X+1,P1] end};
2 -> {[X, '_', '_'], fun([Z,P1,P2]) -> [Z,P1,P2] =:= [X,P1,P2] end};
@@ -237,14 +236,14 @@ create_pb_key(N,list) ->
_ -> {[X, '$1', '$2'], fun([Z,P1,P2]) -> [Z,P1,P2] =:= [X,P1,P2] end}
end;
create_pb_key(N, tuple) ->
- X = random:uniform(N),
- case random:uniform(2) of
+ X = rand:uniform(N),
+ case rand:uniform(2) of
1 -> {{X, X+1, '$1'},fun({Z,Z1,P1}) -> {Z,Z1,P1} =:= {X,X+1,P1} end};
_ -> {{X, '$1', '$2'},fun({Z,P1,P2}) -> {Z,P1,P2} =:= {X,P1,P2} end}
end;
create_pb_key(N, complex) ->
- X = random:uniform(N),
- case random:uniform(2) of
+ X = rand:uniform(N),
+ case rand:uniform(2) of
1 -> {{[X, X+1], '$1'}, fun({[Z,Z1],P1}) ->
{[Z,Z1],P1} =:= {[X,X+1],P1} end};
_ -> {{[X, '$1'], '$2'},fun({[Z,P1],P2}) ->
diff --git a/lib/stdlib/test/sets_SUITE.erl b/lib/stdlib/test/sets_SUITE.erl
index 972a812072..e7fc5595a9 100644
--- a/lib/stdlib/test/sets_SUITE.erl
+++ b/lib/stdlib/test/sets_SUITE.erl
@@ -107,9 +107,9 @@ add_element_del([H|T], M, S, Del, []) ->
add_element_del(T, M, M(add_element, {H,S}), Del, [H]);
add_element_del([H|T], M, S0, Del, Inserted) ->
S1 = M(add_element, {H,S0}),
- case random:uniform(3) of
+ case rand:uniform(3) of
1 ->
- OldEl = lists:nth(random:uniform(length(Inserted)), Inserted),
+ OldEl = lists:nth(rand:uniform(length(Inserted)), Inserted),
S = M(del_element, {OldEl,S1}),
add_element_del(T, M, S, [OldEl|Del], [H|Inserted]);
_ ->
@@ -438,7 +438,7 @@ iterate_1(M) ->
M(empty, []).
iterate_2(M) ->
- random:seed(1, 2, 42),
+ rand:seed(exsplus, {1,2,42}),
iter_set(M, 1000).
iter_set(_M, 0) ->
@@ -447,7 +447,7 @@ iter_set(M, N) ->
L = [I || I <- lists:seq(1, N)],
T = M(from_list, L),
L = lists:reverse(iterate_set(M, T)),
- R = random:uniform(N),
+ R = rand:uniform(N),
S = lists:reverse(iterate_set(M, R, T)),
S = [E || E <- L, E >= R],
iter_set(M, N-1).
@@ -481,7 +481,7 @@ sets_mods() ->
test_all(Tester) ->
Res = [begin
- random:seed(1, 2, 42),
+ rand:seed(exsplus, {1,2,42}),
S = Tester(M),
{M(size, S),lists:sort(M(to_list, S))}
end || M <- sets_mods()],
@@ -492,7 +492,7 @@ test_all([{Low,High}|T], Tester) ->
test_all([Sz|T], Tester) when is_integer(Sz) ->
List = rnd_list(Sz),
Res = [begin
- random:seed(19, 2, Sz),
+ rand:seed(exsplus, {19,2,Sz}),
S = Tester(List, M),
{M(size, S),lists:sort(M(to_list, S))}
end || M <- sets_mods()],
@@ -512,10 +512,10 @@ rnd_list(Sz) ->
rnd_list_1(Sz, []).
atomic_rnd_term() ->
- case random:uniform(3) of
- 1 -> list_to_atom(integer_to_list($\s+random:uniform(94))++"rnd");
- 2 -> random:uniform();
- 3 -> random:uniform(50)-37
+ case rand:uniform(3) of
+ 1 -> list_to_atom(integer_to_list($\s+rand:uniform(94))++"rnd");
+ 2 -> rand:uniform();
+ 3 -> rand:uniform(50)-37
end.
rnd_list_1(0, Acc) -> Acc;
@@ -543,7 +543,7 @@ remove_some(List0, P) ->
end.
remove_some([H|T], P, Acc) ->
- case random:uniform() of
+ case rand:uniform() of
F when F < P -> %Remove.
remove_some(T, P, Acc);
_ ->
diff --git a/lib/stdlib/test/timer_SUITE.erl b/lib/stdlib/test/timer_SUITE.erl
index 057d82fb65..10dcfad76f 100644
--- a/lib/stdlib/test/timer_SUITE.erl
+++ b/lib/stdlib/test/timer_SUITE.erl
@@ -80,8 +80,6 @@ report_result(Error) -> ?line test_server:fail(Error).
big_test(N) ->
C = start_collect(),
system_time(), system_time(), system_time(),
- random:seed(erlang:timestamp()),
- random:uniform(100),random:uniform(100),random:uniform(100),
big_loop(C, N, []),
@@ -127,17 +125,17 @@ big_loop(C, N, Pids) ->
after 0 ->
%% maybe start an interval timer test
- Pids1 = maybe_start_i_test(Pids, C, random:uniform(4)),
+ Pids1 = maybe_start_i_test(Pids, C, rand:uniform(4)),
%% start 1-4 "after" tests
- Pids2 = start_after_test(Pids1, C, random:uniform(4)),
+ Pids2 = start_after_test(Pids1, C, rand:uniform(4)),
%%Pids2=Pids1,
%% wait a little while
- timer:sleep(random:uniform(200)*3),
+ timer:sleep(rand:uniform(200)*3),
%% spawn zero, one or two nrev to get some load ;-/
- Pids3 = start_nrev(Pids2, random:uniform(100)),
+ Pids3 = start_nrev(Pids2, rand:uniform(100)),
big_loop(C, N-1, Pids3)
end.
@@ -148,20 +146,20 @@ start_nrev(Pids, N) when N < 25 ->
start_nrev(Pids, N) when N < 75 ->
[spawn_link(timer_SUITE, do_nrev, [1])|Pids];
start_nrev(Pids, _N) ->
- NrevPid1 = spawn_link(timer_SUITE, do_nrev, [random:uniform(1000)*10]),
+ NrevPid1 = spawn_link(timer_SUITE, do_nrev, [rand:uniform(1000)*10]),
NrevPid2 = spawn_link(timer_SUITE, do_nrev, [1]),
[NrevPid1,NrevPid2|Pids].
start_after_test(Pids, C, 1) ->
- TO1 = random:uniform(100)*47,
+ TO1 = rand:uniform(100)*47,
[s_a_t(C, TO1)|Pids];
start_after_test(Pids, C, 2) ->
- TO1 = random:uniform(100)*47,
- TO2 = TO1 div random:uniform(3) + 101,
+ TO1 = rand:uniform(100)*47,
+ TO2 = TO1 div rand:uniform(3) + 101,
[s_a_t(C, TO1),s_a_t(C, TO2)|Pids];
start_after_test(Pids, C, N) ->
- TO1 = random:uniform(100)*47,
+ TO1 = rand:uniform(100)*47,
start_after_test([s_a_t(C, TO1)|Pids], C, N-1).
s_a_t(C, TimeOut) ->
@@ -187,8 +185,8 @@ a_t(C, TimeOut) ->
maybe_start_i_test(Pids, C, 1) ->
%% ok do it
- TOI = random:uniform(53)*49,
- CountI = random:uniform(10) + 3, % at least 4 times
+ TOI = rand:uniform(53)*49,
+ CountI = rand:uniform(10) + 3, % at least 4 times
[spawn_link(timer_SUITE, i_t, [C, TOI, CountI])|Pids];
maybe_start_i_test(Pids, _C, _) ->
Pids.
diff --git a/lib/syntax_tools/src/erl_syntax_lib.erl b/lib/syntax_tools/src/erl_syntax_lib.erl
index 5b5b18d15b..58c4cc5244 100644
--- a/lib/syntax_tools/src/erl_syntax_lib.erl
+++ b/lib/syntax_tools/src/erl_syntax_lib.erl
@@ -359,9 +359,9 @@ new_variable_name(S) ->
%% within a reasonably small range relative to the number of elements in
%% the set.
%%
-%% This function uses the module `random' to generate new
+%% This function uses the module `rand' to generate new
%% keys. The seed it uses may be initialized by calling
-%% `random:seed/0' or `random:seed/3' before this
+%% `rand:seed/1' or `rand:seed/2' before this
%% function is first called.
%%
%% @see new_variable_name/1
@@ -404,7 +404,13 @@ start_range(S) ->
%% order, but (pseudo-)randomly distributed over the range.
generate(_Key, Range) ->
- random:uniform(Range). % works well
+ _ = case rand:export_seed() of
+ undefined ->
+ rand:seed(exsplus, {753,8,73});
+ _ ->
+ ok
+ end,
+ rand:uniform(Range). % works well
%% =====================================================================
diff --git a/lib/test_server/src/test_server_ctrl.erl b/lib/test_server/src/test_server_ctrl.erl
index 0be6e0b4e4..cd08a25bd8 100644
--- a/lib/test_server/src/test_server_ctrl.erl
+++ b/lib/test_server/src/test_server_ctrl.erl
@@ -3163,11 +3163,17 @@ delete_prop([], Props) ->
%% Shuffles the order of Cases.
shuffle_cases(Ref, Cases, undefined) ->
- shuffle_cases(Ref, Cases, ?now);
+ shuffle_cases(Ref, Cases, rand:seed_s(exsplus));
-shuffle_cases(Ref, [{conf,Ref,_,_}=Start | Cases], Seed) ->
+shuffle_cases(Ref, [{conf,Ref,_,_}=Start | Cases], Seed0) ->
{N,CasesToShuffle,Rest} = cases_to_shuffle(Ref, Cases),
- ShuffledCases = random_order(N, random:uniform_s(N, Seed), CasesToShuffle, []),
+ Seed = case Seed0 of
+ {X,Y,Z} when is_integer(X+Y+Z) ->
+ rand:seed(exsplus, Seed0);
+ _ ->
+ Seed0
+ end,
+ ShuffledCases = random_order(N, rand:uniform_s(N, Seed), CasesToShuffle, []),
[Start|ShuffledCases] ++ Rest.
cases_to_shuffle(Ref, Cases) ->
@@ -3201,7 +3207,7 @@ random_order(1, {_Pos,Seed}, [{_Ix,CaseOrGroup}], Shuffled) ->
Shuffled++CaseOrGroup;
random_order(N, {Pos,NewSeed}, IxCases, Shuffled) ->
{First,[{_Ix,CaseOrGroup}|Rest]} = lists:split(Pos-1, IxCases),
- random_order(N-1, random:uniform_s(N-1, NewSeed),
+ random_order(N-1, rand:uniform_s(N-1, NewSeed),
First++Rest, Shuffled++CaseOrGroup).
@@ -3711,8 +3717,8 @@ run_test_case1(Ref, Num, Mod, Func, Args, RunInit,
RunDir = filename:dirname(MinorName),
Ext =
if Num == 0 ->
- Nr = erlang:unique_integer([positive]),
- lists:flatten(io_lib:format(".~w", [Nr]));
+ Int = erlang:unique_integer([positive,monotonic]),
+ lists:flatten(io_lib:format(".cfg.~w", [Int]));
true ->
lists:flatten(io_lib:format(".~w", [Num]))
end,
diff --git a/lib/test_server/src/test_server_node.erl b/lib/test_server/src/test_server_node.erl
index 4e6839fc6b..3419f3f5d0 100644
--- a/lib/test_server/src/test_server_node.erl
+++ b/lib/test_server/src/test_server_node.erl
@@ -619,8 +619,7 @@ do_quote_progname([Prog,Arg|Args]) ->
end.
random_element(L) ->
- random:seed(os:timestamp()),
- lists:nth(random:uniform(length(L)), L).
+ lists:nth(rand:uniform(length(L)), L).
find_release(latest) ->
"/usr/local/otp/releases/latest/bin/erl";
diff --git a/lib/tools/src/make.erl b/lib/tools/src/make.erl
index 96c3e0e506..5d5a1ef2bd 100644
--- a/lib/tools/src/make.erl
+++ b/lib/tools/src/make.erl
@@ -25,12 +25,20 @@
%% If Emakefile is missing the current directory is used.
-module(make).
--export([all/0,all/1,files/1,files/2]).
+-export([all_or_nothing/0,all/0,all/1,files/1,files/2]).
-include_lib("kernel/include/file.hrl").
-define(MakeOpts,[noexec,load,netload,noload]).
+all_or_nothing() ->
+ case all() of
+ up_to_date ->
+ up_to_date;
+ error ->
+ halt(1)
+ end.
+
all() ->
all([]).
diff --git a/lib/wx/api_gen/gl_gen_erl.erl b/lib/wx/api_gen/gl_gen_erl.erl
index 20406a8d05..84e9600bc0 100644
--- a/lib/wx/api_gen/gl_gen_erl.erl
+++ b/lib/wx/api_gen/gl_gen_erl.erl
@@ -226,10 +226,14 @@ gen_types(Where) ->
w("-type clamp() :: float(). %% 0.0..1.0~n", []),
w("-type offset() :: non_neg_integer(). %% Offset in memory block~n", [])
end,
- w("-type matrix() :: {float(),float(),float(),float(),~n", []),
+ w("-type matrix12() :: {float(),float(),float(),float(),~n", []),
+ w(" float(),float(),float(),float(),~n", []),
+ w(" float(),float(),float(),float()}.~n", []),
+ w("-type matrix16() :: {float(),float(),float(),float(),~n", []),
w(" float(),float(),float(),float(),~n", []),
w(" float(),float(),float(),float(),~n", []),
w(" float(),float(),float(),float()}.~n", []),
+ w("-type matrix() :: matrix12() | matrix16().~n", []),
w("-type mem() :: binary() | tuple(). %% Memory block~n", []),
ok.
@@ -480,10 +484,12 @@ doc_arg_type2(T=#type{single=true}) ->
doc_arg_type3(T);
doc_arg_type2(T=#type{single=undefined}) ->
doc_arg_type3(T);
-doc_arg_type2(T=#type{single={tuple,undefined}}) ->
- "{" ++ doc_arg_type3(T) ++ "}";
+doc_arg_type2(_T=#type{single={tuple,undefined}}) ->
+ "tuple()";
doc_arg_type2(#type{base=float, single={tuple,16}}) ->
"matrix()";
+doc_arg_type2(#type{base=string, single=list}) ->
+ "iolist()";
doc_arg_type2(T=#type{single={tuple,Sz}}) ->
"{" ++ args(fun doc_arg_type3/1, ",", lists:duplicate(Sz,T)) ++ "}";
doc_arg_type2(T=#type{single=list}) ->
diff --git a/lib/wx/api_gen/wx_extra/added_func.h b/lib/wx/api_gen/wx_extra/added_func.h
index 2323529368..0698621c5f 100644
--- a/lib/wx/api_gen/wx_extra/added_func.h
+++ b/lib/wx/api_gen/wx_extra/added_func.h
@@ -26,3 +26,9 @@ class WXDLLIMPEXP_AUI wxAuiPaneInfo
wxPoint GetFloatingPosition();
wxSize GetFloatingSize();
};
+
+class wxToolBar {
+ public:
+ wxToolBarToolBase * AddStretchableSpace();
+ wxToolBarToolBase * InsertStretchableSpace(size_t pos);
+};
diff --git a/lib/wx/api_gen/wx_extra/wxEvtHandler.c_src b/lib/wx/api_gen/wx_extra/wxEvtHandler.c_src
index 5e02066309..08fef1c2ff 100644
--- a/lib/wx/api_gen/wx_extra/wxEvtHandler.c_src
+++ b/lib/wx/api_gen/wx_extra/wxEvtHandler.c_src
@@ -42,11 +42,15 @@ case 101: { // wxEvtHandler::Disconnect
int eventType = wxeEventTypeFromAtom(bp); bp += *eventTypeLen;
if(eventType > 0) {
+ if(recurse_level > 1) {
+ delayed_delete->Append(Ecmd.Save());
+ } else {
bool Result = This->Disconnect((int) *winid,(int) *lastId,eventType,
(wxObjectEventFunction)(wxEventFunction)
&wxeEvtListener::forward,
NULL, Listener);
rt.addBool(Result);
+ }
} else {
rt.addAtom("badarg");
rt.addAtom("event_type");
diff --git a/lib/wx/api_gen/wx_gen_cpp.erl b/lib/wx/api_gen/wx_gen_cpp.erl
index 5649336b5d..ed7b27f3bf 100644
--- a/lib/wx/api_gen/wx_gen_cpp.erl
+++ b/lib/wx/api_gen/wx_gen_cpp.erl
@@ -1141,6 +1141,7 @@ gen_macros() ->
w("#include <wx/html/htmlcell.h>~n"),
w("#include <wx/filename.h>~n"),
w("#include <wx/sysopt.h>~n"),
+ w("#include <wx/overlay.h>~n"),
w("~n~n", []),
w("#ifndef wxICON_DEFAULT_BITMAP_TYPE~n",[]),
@@ -1276,6 +1277,11 @@ encode_events(Evs) ->
w(" } else {~n"),
w(" send_res = rt.send();~n"),
w(" if(cb->skip) event->Skip();~n"),
+ w(" if(app->recurse_level < 1) {~n"),
+ w(" app->recurse_level++;~n"),
+ w(" app->dispatch_cmds();~n"),
+ w(" app->recurse_level--;~n"),
+ w(" }~n"),
w(" };~n"),
w(" return send_res;~n"),
w(" }~n").
diff --git a/lib/wx/api_gen/wxapi.conf b/lib/wx/api_gen/wxapi.conf
index f076323bea..f5a6751696 100644
--- a/lib/wx/api_gen/wxapi.conf
+++ b/lib/wx/api_gen/wxapi.conf
@@ -367,7 +367,7 @@
{class,wxMirrorDC, wxDC, [], ['wxMirrorDC', '~wxMirrorDC']}.
{class,wxScreenDC, wxDC, [], ['wxScreenDC', '~wxScreenDC']}.
-{class,wxPostScriptDC,wxDC,[],
+{class,wxPostScriptDC,wxDC,[{ifdef, wxUSE_POSTSCRIPT}],
['wxPostScriptDC','~wxPostScriptDC',
{'SetResolution', [{deprecated, "!wxCHECK_VERSION(2,9,0)"}]},
{'GetResolution', [{deprecated, "!wxCHECK_VERSION(2,9,0)"}]}]}.
@@ -493,6 +493,8 @@
{class, wxToolBar, wxControl, [],
['AddControl','AddSeparator','AddTool','AddCheckTool','AddRadioTool',
+ {'AddStretchableSpace', [{test_if, "wxCHECK_VERSION(3,0,0)"}]},
+ {'InsertStretchableSpace', [{test_if, "wxCHECK_VERSION(3,0,0)"}]},
'DeleteTool','DeleteToolByPos','EnableTool','FindById','FindControl',
'FindToolForPosition','GetToolSize','GetToolBitmapSize','GetMargins',
%%'GetToolClientData' , %%'SetToolClientData',
@@ -1975,3 +1977,9 @@
{class, wxMouseCaptureLostEvent, wxEvent,
[{event,[wxEVT_MOUSE_CAPTURE_LOST]}],[]}.
+
+{class, wxOverlay, root, [],
+ ['wxOverlay', '~wxOverlay', 'Reset']}.
+
+{class, wxDCOverlay, root, [],
+ ['wxDCOverlay', '~wxDCOverlay', 'Clear']}.
diff --git a/lib/wx/c_src/gen/wxe_derived_dest.h b/lib/wx/c_src/gen/wxe_derived_dest.h
index 03d1502c2a..1dcf029244 100644
--- a/lib/wx/c_src/gen/wxe_derived_dest.h
+++ b/lib/wx/c_src/gen/wxe_derived_dest.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2008-2014. All Rights Reserved.
+ * Copyright Ericsson AB 2008-2015. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -86,11 +86,13 @@ class EwxScreenDC : public wxScreenDC {
EwxScreenDC() : wxScreenDC() {};
};
+#if wxUSE_POSTSCRIPT
class EwxPostScriptDC : public wxPostScriptDC {
public: ~EwxPostScriptDC() {((WxeApp *)wxTheApp)->clearPtr(this);};
EwxPostScriptDC(const wxPrintData& printData) : wxPostScriptDC(printData) {};
EwxPostScriptDC() : wxPostScriptDC() {};
};
+#endif // wxUSE_POSTSCRIPT
class EwxWindowDC : public wxWindowDC {
public: ~EwxWindowDC() {((WxeApp *)wxTheApp)->clearPtr(this);};
@@ -787,3 +789,9 @@ class EwxPopupTransientWindow : public wxPopupTransientWindow {
};
#endif // wxUSE_POPUPWIN
+class EwxDCOverlay : public wxDCOverlay {
+ public: ~EwxDCOverlay() {((WxeApp *)wxTheApp)->clearPtr(this);};
+ EwxDCOverlay(wxOverlay& overlay,wxWindowDC * dc,int x,int y,int width,int height) : wxDCOverlay(overlay,dc,x,y,width,height) {};
+ EwxDCOverlay(wxOverlay& overlay,wxWindowDC * dc) : wxDCOverlay(overlay,dc) {};
+};
+
diff --git a/lib/wx/c_src/gen/wxe_events.cpp b/lib/wx/c_src/gen/wxe_events.cpp
index a532ee985d..4affe2ba53 100644
--- a/lib/wx/c_src/gen/wxe_events.cpp
+++ b/lib/wx/c_src/gen/wxe_events.cpp
@@ -897,6 +897,11 @@ case 235: {// wxMouseCaptureLostEvent
} else {
send_res = rt.send();
if(cb->skip) event->Skip();
+ if(app->recurse_level < 1) {
+ app->recurse_level++;
+ app->dispatch_cmds();
+ app->recurse_level--;
+ }
};
return send_res;
}
diff --git a/lib/wx/c_src/gen/wxe_funcs.cpp b/lib/wx/c_src/gen/wxe_funcs.cpp
index 3211664499..b2830dbc63 100644
--- a/lib/wx/c_src/gen/wxe_funcs.cpp
+++ b/lib/wx/c_src/gen/wxe_funcs.cpp
@@ -113,11 +113,15 @@ case 101: { // wxEvtHandler::Disconnect
int eventType = wxeEventTypeFromAtom(bp); bp += *eventTypeLen;
if(eventType > 0) {
+ if(recurse_level > 1) {
+ delayed_delete->Append(Ecmd.Save());
+ } else {
bool Result = This->Disconnect((int) *winid,(int) *lastId,eventType,
(wxObjectEventFunction)(wxEventFunction)
&wxeEvtListener::forward,
NULL, Listener);
rt.addBool(Result);
+ }
} else {
rt.addAtom("badarg");
rt.addAtom("event_type");
@@ -5856,6 +5860,7 @@ case wxScreenDC_new: { // wxScreenDC::wxScreenDC
rt.addRef(getRef((void *)Result,memenv), "wxScreenDC");
break;
}
+#if wxUSE_POSTSCRIPT
case wxPostScriptDC_new_0: { // wxPostScriptDC::wxPostScriptDC
wxPostScriptDC * Result = new EwxPostScriptDC();
newPtr((void *) Result, 4, memenv);
@@ -5883,6 +5888,7 @@ case wxPostScriptDC_GetResolution: { // wxPostScriptDC::GetResolution
break;
}
#endif
+#endif // wxUSE_POSTSCRIPT
#if !wxCHECK_VERSION(2,9,0)
case wxWindowDC_new_0: { // wxWindowDC::wxWindowDC
wxWindowDC * Result = new EwxWindowDC();
@@ -8514,6 +8520,25 @@ data = (wxObject *) getPtr(bp,memenv); bp += 4;
rt.addRef(getRef((void *)Result,memenv), "wx");
break;
}
+#if wxCHECK_VERSION(3,0,0)
+case wxToolBar_AddStretchableSpace: { // wxToolBar::AddStretchableSpace
+ wxToolBar *This = (wxToolBar *) getPtr(bp,memenv); bp += 4;
+ if(!This) throw wxe_badarg(0);
+ wxToolBarToolBase * Result = (wxToolBarToolBase*)This->AddStretchableSpace();
+ rt.addRef(getRef((void *)Result,memenv), "wx");
+ break;
+}
+#endif
+#if wxCHECK_VERSION(3,0,0)
+case wxToolBar_InsertStretchableSpace: { // wxToolBar::InsertStretchableSpace
+ wxToolBar *This = (wxToolBar *) getPtr(bp,memenv); bp += 4;
+ int * pos = (int *) bp; bp += 4;
+ if(!This) throw wxe_badarg(0);
+ wxToolBarToolBase * Result = (wxToolBarToolBase*)This->InsertStretchableSpace(*pos);
+ rt.addRef(getRef((void *)Result,memenv), "wx");
+ break;
+}
+#endif
case wxToolBar_DeleteTool: { // wxToolBar::DeleteTool
wxToolBar *This = (wxToolBar *) getPtr(bp,memenv); bp += 4;
int * toolid = (int *) bp; bp += 4;
@@ -31959,6 +31984,56 @@ case wxPopupTransientWindow_Dismiss: { // wxPopupTransientWindow::Dismiss
break;
}
#endif // wxUSE_POPUPWIN
+case wxOverlay_new: { // wxOverlay::wxOverlay
+ wxOverlay * Result = new wxOverlay();
+ newPtr((void *) Result, 236, memenv);
+ rt.addRef(getRef((void *)Result,memenv), "wxOverlay");
+ break;
+}
+case wxOverlay_destruct: { // wxOverlay::~wxOverlay
+ wxOverlay *This = (wxOverlay *) getPtr(bp,memenv); bp += 4;
+ if(This) { ((WxeApp *) wxTheApp)->clearPtr((void *) This);
+ delete This;}
+ break;
+}
+case wxOverlay_Reset: { // wxOverlay::Reset
+ wxOverlay *This = (wxOverlay *) getPtr(bp,memenv); bp += 4;
+ if(!This) throw wxe_badarg(0);
+ This->Reset();
+ break;
+}
+case wxDCOverlay_new_6: { // wxDCOverlay::wxDCOverlay
+ wxOverlay *overlay = (wxOverlay *) getPtr(bp,memenv); bp += 4;
+ wxWindowDC *dc = (wxWindowDC *) getPtr(bp,memenv); bp += 4;
+ int * x = (int *) bp; bp += 4;
+ int * y = (int *) bp; bp += 4;
+ int * width = (int *) bp; bp += 4;
+ int * height = (int *) bp; bp += 4;
+ wxDCOverlay * Result = new EwxDCOverlay(*overlay,dc,*x,*y,*width,*height);
+ newPtr((void *) Result, 237, memenv);
+ rt.addRef(getRef((void *)Result,memenv), "wxDCOverlay");
+ break;
+}
+case wxDCOverlay_new_2: { // wxDCOverlay::wxDCOverlay
+ wxOverlay *overlay = (wxOverlay *) getPtr(bp,memenv); bp += 4;
+ wxWindowDC *dc = (wxWindowDC *) getPtr(bp,memenv); bp += 4;
+ wxDCOverlay * Result = new EwxDCOverlay(*overlay,dc);
+ newPtr((void *) Result, 237, memenv);
+ rt.addRef(getRef((void *)Result,memenv), "wxDCOverlay");
+ break;
+}
+case wxDCOverlay_destruct: { // wxDCOverlay::~wxDCOverlay
+ wxDCOverlay *This = (wxDCOverlay *) getPtr(bp,memenv); bp += 4;
+ if(This) { ((WxeApp *) wxTheApp)->clearPtr((void *) This);
+ delete This;}
+ break;
+}
+case wxDCOverlay_Clear: { // wxDCOverlay::Clear
+ wxDCOverlay *This = (wxDCOverlay *) getPtr(bp,memenv); bp += 4;
+ if(!This) throw wxe_badarg(0);
+ This->Clear();
+ break;
+}
default: {
wxeReturn error = wxeReturn(WXE_DRV_PORT, Ecmd.caller, false); error.addAtom("_wxe_error_");
error.addInt((int) Ecmd.op);
@@ -32005,6 +32080,8 @@ bool WxeApp::delete_object(void *ptr, wxeRefData *refd) {
case 215: /* delete (wxBitmapDataObject *) ptr;These objects must be deleted by owner object */ break;
case 227: delete (wxLogNull *) ptr; break;
case 231: delete (EwxLocale *) ptr; return false;
+ case 236: delete (wxOverlay *) ptr; break;
+ case 237: delete (EwxDCOverlay *) ptr; return false;
default: delete (wxObject *) ptr; return false;
}
return true;
diff --git a/lib/wx/c_src/gen/wxe_macros.h b/lib/wx/c_src/gen/wxe_macros.h
index 59f9c7054e..1d50278360 100644
--- a/lib/wx/c_src/gen/wxe_macros.h
+++ b/lib/wx/c_src/gen/wxe_macros.h
@@ -64,6 +64,7 @@
#include <wx/html/htmlcell.h>
#include <wx/filename.h>
#include <wx/sysopt.h>
+#include <wx/overlay.h>
#ifndef wxICON_DEFAULT_BITMAP_TYPE
@@ -911,2505 +912,2514 @@
#define wxToolBar_AddTool_6 981
#define wxToolBar_AddCheckTool 982
#define wxToolBar_AddRadioTool 983
-#define wxToolBar_DeleteTool 984
-#define wxToolBar_DeleteToolByPos 985
-#define wxToolBar_EnableTool 986
-#define wxToolBar_FindById 987
-#define wxToolBar_FindControl 988
-#define wxToolBar_FindToolForPosition 989
-#define wxToolBar_GetToolSize 990
-#define wxToolBar_GetToolBitmapSize 991
-#define wxToolBar_GetMargins 992
-#define wxToolBar_GetToolEnabled 993
-#define wxToolBar_GetToolLongHelp 994
-#define wxToolBar_GetToolPacking 995
-#define wxToolBar_GetToolPos 996
-#define wxToolBar_GetToolSeparation 997
-#define wxToolBar_GetToolShortHelp 998
-#define wxToolBar_GetToolState 999
-#define wxToolBar_InsertControl 1000
-#define wxToolBar_InsertSeparator 1001
-#define wxToolBar_InsertTool_5 1002
-#define wxToolBar_InsertTool_2 1003
-#define wxToolBar_InsertTool_4 1004
-#define wxToolBar_Realize 1005
-#define wxToolBar_RemoveTool 1006
-#define wxToolBar_SetMargins 1007
-#define wxToolBar_SetToolBitmapSize 1008
-#define wxToolBar_SetToolLongHelp 1009
-#define wxToolBar_SetToolPacking 1010
-#define wxToolBar_SetToolShortHelp 1011
-#define wxToolBar_SetToolSeparation 1012
-#define wxToolBar_ToggleTool 1013
-#define wxStatusBar_new_0 1015
-#define wxStatusBar_new_2 1016
-#define wxStatusBar_destruct 1018
-#define wxStatusBar_Create 1019
-#define wxStatusBar_GetFieldRect 1020
-#define wxStatusBar_GetFieldsCount 1021
-#define wxStatusBar_GetStatusText 1022
-#define wxStatusBar_PopStatusText 1023
-#define wxStatusBar_PushStatusText 1024
-#define wxStatusBar_SetFieldsCount 1025
-#define wxStatusBar_SetMinHeight 1026
-#define wxStatusBar_SetStatusText 1027
-#define wxStatusBar_SetStatusWidths 1028
-#define wxStatusBar_SetStatusStyles 1029
-#define wxBitmap_new_0 1030
-#define wxBitmap_new_3 1031
-#define wxBitmap_new_4 1032
-#define wxBitmap_new_2_0 1033
-#define wxBitmap_new_2_1 1034
-#define wxBitmap_destruct 1035
-#define wxBitmap_ConvertToImage 1036
-#define wxBitmap_CopyFromIcon 1037
-#define wxBitmap_Create 1038
-#define wxBitmap_GetDepth 1039
-#define wxBitmap_GetHeight 1040
-#define wxBitmap_GetPalette 1041
-#define wxBitmap_GetMask 1042
-#define wxBitmap_GetWidth 1043
-#define wxBitmap_GetSubBitmap 1044
-#define wxBitmap_LoadFile 1045
-#define wxBitmap_Ok 1046
-#define wxBitmap_SaveFile 1047
-#define wxBitmap_SetDepth 1048
-#define wxBitmap_SetHeight 1049
-#define wxBitmap_SetMask 1050
-#define wxBitmap_SetPalette 1051
-#define wxBitmap_SetWidth 1052
-#define wxIcon_new_0 1053
-#define wxIcon_new_2 1054
-#define wxIcon_new_1 1055
-#define wxIcon_CopyFromBitmap 1056
-#define wxIcon_destroy 1057
-#define wxIconBundle_new_0 1058
-#define wxIconBundle_new_2 1059
-#define wxIconBundle_new_1_0 1060
-#define wxIconBundle_new_1_1 1061
-#define wxIconBundle_destruct 1062
-#define wxIconBundle_AddIcon_2 1063
-#define wxIconBundle_AddIcon_1 1064
-#define wxIconBundle_GetIcon_1_1 1065
-#define wxIconBundle_GetIcon_1_0 1066
-#define wxCursor_new_0 1067
-#define wxCursor_new_1_0 1068
-#define wxCursor_new_1_1 1069
-#define wxCursor_new_4 1070
-#define wxCursor_destruct 1071
-#define wxCursor_Ok 1072
-#define wxMask_new_0 1073
-#define wxMask_new_2_1 1074
-#define wxMask_new_2_0 1075
-#define wxMask_new_1 1076
-#define wxMask_destruct 1077
-#define wxMask_Create_2_1 1078
-#define wxMask_Create_2_0 1079
-#define wxMask_Create_1 1080
-#define wxImage_new_0 1081
-#define wxImage_new_3_0 1082
-#define wxImage_new_4 1083
-#define wxImage_new_5 1084
-#define wxImage_new_2 1085
-#define wxImage_new_3_1 1086
-#define wxImage_Blur 1087
-#define wxImage_BlurHorizontal 1088
-#define wxImage_BlurVertical 1089
-#define wxImage_ConvertAlphaToMask 1090
-#define wxImage_ConvertToGreyscale 1091
-#define wxImage_ConvertToMono 1092
-#define wxImage_Copy 1093
-#define wxImage_Create_3 1094
-#define wxImage_Create_4 1095
-#define wxImage_Create_5 1096
-#define wxImage_Destroy 1097
-#define wxImage_FindFirstUnusedColour 1098
-#define wxImage_GetImageExtWildcard 1099
-#define wxImage_GetAlpha_2 1100
-#define wxImage_GetAlpha_0 1101
-#define wxImage_GetBlue 1102
-#define wxImage_GetData 1103
-#define wxImage_GetGreen 1104
-#define wxImage_GetImageCount 1105
-#define wxImage_GetHeight 1106
-#define wxImage_GetMaskBlue 1107
-#define wxImage_GetMaskGreen 1108
-#define wxImage_GetMaskRed 1109
-#define wxImage_GetOrFindMaskColour 1110
-#define wxImage_GetPalette 1111
-#define wxImage_GetRed 1112
-#define wxImage_GetSubImage 1113
-#define wxImage_GetWidth 1114
-#define wxImage_HasAlpha 1115
-#define wxImage_HasMask 1116
-#define wxImage_GetOption 1117
-#define wxImage_GetOptionInt 1118
-#define wxImage_HasOption 1119
-#define wxImage_InitAlpha 1120
-#define wxImage_InitStandardHandlers 1121
-#define wxImage_IsTransparent 1122
-#define wxImage_LoadFile_2 1123
-#define wxImage_LoadFile_3 1124
-#define wxImage_Ok 1125
-#define wxImage_RemoveHandler 1126
-#define wxImage_Mirror 1127
-#define wxImage_Replace 1128
-#define wxImage_Rescale 1129
-#define wxImage_Resize 1130
-#define wxImage_Rotate 1131
-#define wxImage_RotateHue 1132
-#define wxImage_Rotate90 1133
-#define wxImage_SaveFile_1 1134
-#define wxImage_SaveFile_2_0 1135
-#define wxImage_SaveFile_2_1 1136
-#define wxImage_Scale 1137
-#define wxImage_Size 1138
-#define wxImage_SetAlpha_3 1139
-#define wxImage_SetAlpha_2 1140
-#define wxImage_SetData_2 1141
-#define wxImage_SetData_4 1142
-#define wxImage_SetMask 1143
-#define wxImage_SetMaskColour 1144
-#define wxImage_SetMaskFromImage 1145
-#define wxImage_SetOption_2_1 1146
-#define wxImage_SetOption_2_0 1147
-#define wxImage_SetPalette 1148
-#define wxImage_SetRGB_5 1149
-#define wxImage_SetRGB_4 1150
-#define wxImage_destroy 1151
-#define wxBrush_new_0 1152
-#define wxBrush_new_2 1153
-#define wxBrush_new_1 1154
-#define wxBrush_destruct 1156
-#define wxBrush_GetColour 1157
-#define wxBrush_GetStipple 1158
-#define wxBrush_GetStyle 1159
-#define wxBrush_IsHatch 1160
-#define wxBrush_IsOk 1161
-#define wxBrush_SetColour_1 1162
-#define wxBrush_SetColour_3 1163
-#define wxBrush_SetStipple 1164
-#define wxBrush_SetStyle 1165
-#define wxPen_new_0 1166
-#define wxPen_new_2 1167
-#define wxPen_destruct 1168
-#define wxPen_GetCap 1169
-#define wxPen_GetColour 1170
-#define wxPen_GetJoin 1171
-#define wxPen_GetStyle 1172
-#define wxPen_GetWidth 1173
-#define wxPen_IsOk 1174
-#define wxPen_SetCap 1175
-#define wxPen_SetColour_1 1176
-#define wxPen_SetColour_3 1177
-#define wxPen_SetJoin 1178
-#define wxPen_SetStyle 1179
-#define wxPen_SetWidth 1180
-#define wxRegion_new_0 1181
-#define wxRegion_new_4 1182
-#define wxRegion_new_2 1183
-#define wxRegion_new_1_1 1184
-#define wxRegion_new_1_0 1186
-#define wxRegion_destruct 1188
-#define wxRegion_Clear 1189
-#define wxRegion_Contains_2 1190
-#define wxRegion_Contains_1_0 1191
-#define wxRegion_Contains_4 1192
-#define wxRegion_Contains_1_1 1193
-#define wxRegion_ConvertToBitmap 1194
-#define wxRegion_GetBox 1195
-#define wxRegion_Intersect_4 1196
-#define wxRegion_Intersect_1_1 1197
-#define wxRegion_Intersect_1_0 1198
-#define wxRegion_IsEmpty 1199
-#define wxRegion_Subtract_4 1200
-#define wxRegion_Subtract_1_1 1201
-#define wxRegion_Subtract_1_0 1202
-#define wxRegion_Offset_2 1203
-#define wxRegion_Offset_1 1204
-#define wxRegion_Union_4 1205
-#define wxRegion_Union_1_2 1206
-#define wxRegion_Union_1_1 1207
-#define wxRegion_Union_1_0 1208
-#define wxRegion_Union_3 1209
-#define wxRegion_Xor_4 1210
-#define wxRegion_Xor_1_1 1211
-#define wxRegion_Xor_1_0 1212
-#define wxAcceleratorTable_new_0 1213
-#define wxAcceleratorTable_new_2 1214
-#define wxAcceleratorTable_destruct 1215
-#define wxAcceleratorTable_Ok 1216
-#define wxAcceleratorEntry_new_1_0 1217
-#define wxAcceleratorEntry_new_1_1 1218
-#define wxAcceleratorEntry_GetCommand 1219
-#define wxAcceleratorEntry_GetFlags 1220
-#define wxAcceleratorEntry_GetKeyCode 1221
-#define wxAcceleratorEntry_Set 1222
-#define wxAcceleratorEntry_destroy 1223
-#define wxCaret_new_3 1228
-#define wxCaret_new_2 1229
-#define wxCaret_destruct 1231
-#define wxCaret_Create_3 1232
-#define wxCaret_Create_2 1233
-#define wxCaret_GetBlinkTime 1234
-#define wxCaret_GetPosition 1236
-#define wxCaret_GetSize 1238
-#define wxCaret_GetWindow 1239
-#define wxCaret_Hide 1240
-#define wxCaret_IsOk 1241
-#define wxCaret_IsVisible 1242
-#define wxCaret_Move_2 1243
-#define wxCaret_Move_1 1244
-#define wxCaret_SetBlinkTime 1245
-#define wxCaret_SetSize_2 1246
-#define wxCaret_SetSize_1 1247
-#define wxCaret_Show 1248
-#define wxSizer_Add_2_1 1249
-#define wxSizer_Add_2_0 1250
-#define wxSizer_Add_3 1251
-#define wxSizer_Add_2_3 1252
-#define wxSizer_Add_2_2 1253
-#define wxSizer_AddSpacer 1254
-#define wxSizer_AddStretchSpacer 1255
-#define wxSizer_CalcMin 1256
-#define wxSizer_Clear 1257
-#define wxSizer_Detach_1_2 1258
-#define wxSizer_Detach_1_1 1259
-#define wxSizer_Detach_1_0 1260
-#define wxSizer_Fit 1261
-#define wxSizer_FitInside 1262
-#define wxSizer_GetChildren 1263
-#define wxSizer_GetItem_2_1 1264
-#define wxSizer_GetItem_2_0 1265
-#define wxSizer_GetItem_1 1266
-#define wxSizer_GetSize 1267
-#define wxSizer_GetPosition 1268
-#define wxSizer_GetMinSize 1269
-#define wxSizer_Hide_2_0 1270
-#define wxSizer_Hide_2_1 1271
-#define wxSizer_Hide_1 1272
-#define wxSizer_Insert_3_1 1273
-#define wxSizer_Insert_3_0 1274
-#define wxSizer_Insert_4 1275
-#define wxSizer_Insert_3_3 1276
-#define wxSizer_Insert_3_2 1277
-#define wxSizer_Insert_2 1278
-#define wxSizer_InsertSpacer 1279
-#define wxSizer_InsertStretchSpacer 1280
-#define wxSizer_IsShown_1_2 1281
-#define wxSizer_IsShown_1_1 1282
-#define wxSizer_IsShown_1_0 1283
-#define wxSizer_Layout 1284
-#define wxSizer_Prepend_2_1 1285
-#define wxSizer_Prepend_2_0 1286
-#define wxSizer_Prepend_3 1287
-#define wxSizer_Prepend_2_3 1288
-#define wxSizer_Prepend_2_2 1289
-#define wxSizer_Prepend_1 1290
-#define wxSizer_PrependSpacer 1291
-#define wxSizer_PrependStretchSpacer 1292
-#define wxSizer_RecalcSizes 1293
-#define wxSizer_Remove_1_1 1294
-#define wxSizer_Remove_1_0 1295
-#define wxSizer_Replace_3_1 1296
-#define wxSizer_Replace_3_0 1297
-#define wxSizer_Replace_2 1298
-#define wxSizer_SetDimension 1299
-#define wxSizer_SetMinSize_2 1300
-#define wxSizer_SetMinSize_1 1301
-#define wxSizer_SetItemMinSize_3_2 1302
-#define wxSizer_SetItemMinSize_2_2 1303
-#define wxSizer_SetItemMinSize_3_1 1304
-#define wxSizer_SetItemMinSize_2_1 1305
-#define wxSizer_SetItemMinSize_3_0 1306
-#define wxSizer_SetItemMinSize_2_0 1307
-#define wxSizer_SetSizeHints 1308
-#define wxSizer_SetVirtualSizeHints 1309
-#define wxSizer_Show_2_2 1310
-#define wxSizer_Show_2_1 1311
-#define wxSizer_Show_2_0 1312
-#define wxSizer_Show_1 1313
-#define wxSizerFlags_new 1314
-#define wxSizerFlags_Align 1315
-#define wxSizerFlags_Border_2 1316
-#define wxSizerFlags_Border_1 1317
-#define wxSizerFlags_Center 1318
-#define wxSizerFlags_Centre 1319
-#define wxSizerFlags_Expand 1320
-#define wxSizerFlags_Left 1321
-#define wxSizerFlags_Proportion 1322
-#define wxSizerFlags_Right 1323
-#define wxSizerFlags_destroy 1324
-#define wxSizerItem_new_5_1 1325
-#define wxSizerItem_new_2_1 1326
-#define wxSizerItem_new_5_0 1327
-#define wxSizerItem_new_2_0 1328
-#define wxSizerItem_new_6 1329
-#define wxSizerItem_new_3 1330
-#define wxSizerItem_new_0 1331
-#define wxSizerItem_destruct 1332
-#define wxSizerItem_CalcMin 1333
-#define wxSizerItem_DeleteWindows 1334
-#define wxSizerItem_DetachSizer 1335
-#define wxSizerItem_GetBorder 1336
-#define wxSizerItem_GetFlag 1337
-#define wxSizerItem_GetMinSize 1338
-#define wxSizerItem_GetPosition 1339
-#define wxSizerItem_GetProportion 1340
-#define wxSizerItem_GetRatio 1341
-#define wxSizerItem_GetRect 1342
-#define wxSizerItem_GetSize 1343
-#define wxSizerItem_GetSizer 1344
-#define wxSizerItem_GetSpacer 1345
-#define wxSizerItem_GetUserData 1346
-#define wxSizerItem_GetWindow 1347
-#define wxSizerItem_IsSizer 1348
-#define wxSizerItem_IsShown 1349
-#define wxSizerItem_IsSpacer 1350
-#define wxSizerItem_IsWindow 1351
-#define wxSizerItem_SetBorder 1352
-#define wxSizerItem_SetDimension 1353
-#define wxSizerItem_SetFlag 1354
-#define wxSizerItem_SetInitSize 1355
-#define wxSizerItem_SetMinSize_1 1356
-#define wxSizerItem_SetMinSize_2 1357
-#define wxSizerItem_SetProportion 1358
-#define wxSizerItem_SetRatio_2 1359
-#define wxSizerItem_SetRatio_1_1 1360
-#define wxSizerItem_SetRatio_1_0 1361
-#define wxSizerItem_SetSizer 1362
-#define wxSizerItem_SetSpacer_1 1363
-#define wxSizerItem_SetSpacer_2 1364
-#define wxSizerItem_SetWindow 1365
-#define wxSizerItem_Show 1366
-#define wxBoxSizer_new 1367
-#define wxBoxSizer_GetOrientation 1368
-#define wxBoxSizer_destroy 1369
-#define wxStaticBoxSizer_new_2 1370
-#define wxStaticBoxSizer_new_3 1371
-#define wxStaticBoxSizer_GetStaticBox 1372
-#define wxStaticBoxSizer_destroy 1373
-#define wxGridSizer_new_4 1374
-#define wxGridSizer_new_2 1375
-#define wxGridSizer_GetCols 1376
-#define wxGridSizer_GetHGap 1377
-#define wxGridSizer_GetRows 1378
-#define wxGridSizer_GetVGap 1379
-#define wxGridSizer_SetCols 1380
-#define wxGridSizer_SetHGap 1381
-#define wxGridSizer_SetRows 1382
-#define wxGridSizer_SetVGap 1383
-#define wxGridSizer_destroy 1384
-#define wxFlexGridSizer_new_4 1385
-#define wxFlexGridSizer_new_2 1386
-#define wxFlexGridSizer_AddGrowableCol 1387
-#define wxFlexGridSizer_AddGrowableRow 1388
-#define wxFlexGridSizer_GetFlexibleDirection 1389
-#define wxFlexGridSizer_GetNonFlexibleGrowMode 1390
-#define wxFlexGridSizer_RemoveGrowableCol 1391
-#define wxFlexGridSizer_RemoveGrowableRow 1392
-#define wxFlexGridSizer_SetFlexibleDirection 1393
-#define wxFlexGridSizer_SetNonFlexibleGrowMode 1394
-#define wxFlexGridSizer_destroy 1395
-#define wxGridBagSizer_new 1396
-#define wxGridBagSizer_Add_3_2 1397
-#define wxGridBagSizer_Add_3_1 1398
-#define wxGridBagSizer_Add_4 1399
-#define wxGridBagSizer_Add_1_0 1400
-#define wxGridBagSizer_Add_2_1 1401
-#define wxGridBagSizer_Add_2_0 1402
-#define wxGridBagSizer_Add_3_0 1403
-#define wxGridBagSizer_Add_1_1 1404
-#define wxGridBagSizer_CalcMin 1405
-#define wxGridBagSizer_CheckForIntersection_2 1406
-#define wxGridBagSizer_CheckForIntersection_3 1407
-#define wxGridBagSizer_FindItem_1_1 1408
-#define wxGridBagSizer_FindItem_1_0 1409
-#define wxGridBagSizer_FindItemAtPoint 1410
-#define wxGridBagSizer_FindItemAtPosition 1411
-#define wxGridBagSizer_FindItemWithData 1412
-#define wxGridBagSizer_GetCellSize 1413
-#define wxGridBagSizer_GetEmptyCellSize 1414
-#define wxGridBagSizer_GetItemPosition_1_2 1415
-#define wxGridBagSizer_GetItemPosition_1_1 1416
-#define wxGridBagSizer_GetItemPosition_1_0 1417
-#define wxGridBagSizer_GetItemSpan_1_2 1418
-#define wxGridBagSizer_GetItemSpan_1_1 1419
-#define wxGridBagSizer_GetItemSpan_1_0 1420
-#define wxGridBagSizer_SetEmptyCellSize 1421
-#define wxGridBagSizer_SetItemPosition_2_2 1422
-#define wxGridBagSizer_SetItemPosition_2_1 1423
-#define wxGridBagSizer_SetItemPosition_2_0 1424
-#define wxGridBagSizer_SetItemSpan_2_2 1425
-#define wxGridBagSizer_SetItemSpan_2_1 1426
-#define wxGridBagSizer_SetItemSpan_2_0 1427
-#define wxGridBagSizer_destroy 1428
-#define wxStdDialogButtonSizer_new 1429
-#define wxStdDialogButtonSizer_AddButton 1430
-#define wxStdDialogButtonSizer_Realize 1431
-#define wxStdDialogButtonSizer_SetAffirmativeButton 1432
-#define wxStdDialogButtonSizer_SetCancelButton 1433
-#define wxStdDialogButtonSizer_SetNegativeButton 1434
-#define wxStdDialogButtonSizer_destroy 1435
-#define wxFont_new_0 1436
-#define wxFont_new_1 1437
-#define wxFont_new_5 1438
-#define wxFont_destruct 1440
-#define wxFont_IsFixedWidth 1441
-#define wxFont_GetDefaultEncoding 1442
-#define wxFont_GetFaceName 1443
-#define wxFont_GetFamily 1444
-#define wxFont_GetNativeFontInfoDesc 1445
-#define wxFont_GetNativeFontInfoUserDesc 1446
-#define wxFont_GetPointSize 1447
-#define wxFont_GetStyle 1448
-#define wxFont_GetUnderlined 1449
-#define wxFont_GetWeight 1450
-#define wxFont_Ok 1451
-#define wxFont_SetDefaultEncoding 1452
-#define wxFont_SetFaceName 1453
-#define wxFont_SetFamily 1454
-#define wxFont_SetPointSize 1455
-#define wxFont_SetStyle 1456
-#define wxFont_SetUnderlined 1457
-#define wxFont_SetWeight 1458
-#define wxToolTip_Enable 1459
-#define wxToolTip_SetDelay 1460
-#define wxToolTip_new 1461
-#define wxToolTip_SetTip 1462
-#define wxToolTip_GetTip 1463
-#define wxToolTip_GetWindow 1464
-#define wxToolTip_destroy 1465
-#define wxButton_new_3 1467
-#define wxButton_new_0 1468
-#define wxButton_destruct 1469
-#define wxButton_Create 1470
-#define wxButton_GetDefaultSize 1471
-#define wxButton_SetDefault 1472
-#define wxButton_SetLabel 1473
-#define wxBitmapButton_new_4 1475
-#define wxBitmapButton_new_0 1476
-#define wxBitmapButton_Create 1477
-#define wxBitmapButton_GetBitmapDisabled 1478
-#define wxBitmapButton_GetBitmapFocus 1480
-#define wxBitmapButton_GetBitmapLabel 1482
-#define wxBitmapButton_GetBitmapSelected 1484
-#define wxBitmapButton_SetBitmapDisabled 1486
-#define wxBitmapButton_SetBitmapFocus 1487
-#define wxBitmapButton_SetBitmapLabel 1488
-#define wxBitmapButton_SetBitmapSelected 1489
-#define wxBitmapButton_destroy 1490
-#define wxToggleButton_new_0 1491
-#define wxToggleButton_new_4 1492
-#define wxToggleButton_Create 1493
-#define wxToggleButton_GetValue 1494
-#define wxToggleButton_SetValue 1495
-#define wxToggleButton_destroy 1496
-#define wxCalendarCtrl_new_0 1497
-#define wxCalendarCtrl_new_3 1498
-#define wxCalendarCtrl_Create 1499
-#define wxCalendarCtrl_destruct 1500
-#define wxCalendarCtrl_SetDate 1501
-#define wxCalendarCtrl_GetDate 1502
-#define wxCalendarCtrl_EnableYearChange 1503
-#define wxCalendarCtrl_EnableMonthChange 1504
-#define wxCalendarCtrl_EnableHolidayDisplay 1505
-#define wxCalendarCtrl_SetHeaderColours 1506
-#define wxCalendarCtrl_GetHeaderColourFg 1507
-#define wxCalendarCtrl_GetHeaderColourBg 1508
-#define wxCalendarCtrl_SetHighlightColours 1509
-#define wxCalendarCtrl_GetHighlightColourFg 1510
-#define wxCalendarCtrl_GetHighlightColourBg 1511
-#define wxCalendarCtrl_SetHolidayColours 1512
-#define wxCalendarCtrl_GetHolidayColourFg 1513
-#define wxCalendarCtrl_GetHolidayColourBg 1514
-#define wxCalendarCtrl_GetAttr 1515
-#define wxCalendarCtrl_SetAttr 1516
-#define wxCalendarCtrl_SetHoliday 1517
-#define wxCalendarCtrl_ResetAttr 1518
-#define wxCalendarCtrl_HitTest 1519
-#define wxCalendarDateAttr_new_0 1520
-#define wxCalendarDateAttr_new_2_1 1521
-#define wxCalendarDateAttr_new_2_0 1522
-#define wxCalendarDateAttr_SetTextColour 1523
-#define wxCalendarDateAttr_SetBackgroundColour 1524
-#define wxCalendarDateAttr_SetBorderColour 1525
-#define wxCalendarDateAttr_SetFont 1526
-#define wxCalendarDateAttr_SetBorder 1527
-#define wxCalendarDateAttr_SetHoliday 1528
-#define wxCalendarDateAttr_HasTextColour 1529
-#define wxCalendarDateAttr_HasBackgroundColour 1530
-#define wxCalendarDateAttr_HasBorderColour 1531
-#define wxCalendarDateAttr_HasFont 1532
-#define wxCalendarDateAttr_HasBorder 1533
-#define wxCalendarDateAttr_IsHoliday 1534
-#define wxCalendarDateAttr_GetTextColour 1535
-#define wxCalendarDateAttr_GetBackgroundColour 1536
-#define wxCalendarDateAttr_GetBorderColour 1537
-#define wxCalendarDateAttr_GetFont 1538
-#define wxCalendarDateAttr_GetBorder 1539
-#define wxCalendarDateAttr_destroy 1540
-#define wxCheckBox_new_4 1542
-#define wxCheckBox_new_0 1543
-#define wxCheckBox_Create 1544
-#define wxCheckBox_GetValue 1545
-#define wxCheckBox_Get3StateValue 1546
-#define wxCheckBox_Is3rdStateAllowedForUser 1547
-#define wxCheckBox_Is3State 1548
-#define wxCheckBox_IsChecked 1549
-#define wxCheckBox_SetValue 1550
-#define wxCheckBox_Set3StateValue 1551
-#define wxCheckBox_destroy 1552
-#define wxCheckListBox_new_0 1553
-#define wxCheckListBox_new_3 1555
-#define wxCheckListBox_Check 1556
-#define wxCheckListBox_IsChecked 1557
-#define wxCheckListBox_destroy 1558
-#define wxChoice_new_3 1561
-#define wxChoice_new_0 1562
-#define wxChoice_destruct 1564
-#define wxChoice_Create 1566
-#define wxChoice_Delete 1567
-#define wxChoice_GetColumns 1568
-#define wxChoice_SetColumns 1569
-#define wxComboBox_new_0 1570
-#define wxComboBox_new_3 1572
-#define wxComboBox_destruct 1573
-#define wxComboBox_Create 1575
-#define wxComboBox_CanCopy 1576
-#define wxComboBox_CanCut 1577
-#define wxComboBox_CanPaste 1578
-#define wxComboBox_CanRedo 1579
-#define wxComboBox_CanUndo 1580
-#define wxComboBox_Copy 1581
-#define wxComboBox_Cut 1582
-#define wxComboBox_GetInsertionPoint 1583
-#define wxComboBox_GetLastPosition 1584
-#define wxComboBox_GetValue 1585
-#define wxComboBox_Paste 1586
-#define wxComboBox_Redo 1587
-#define wxComboBox_Replace 1588
-#define wxComboBox_Remove 1589
-#define wxComboBox_SetInsertionPoint 1590
-#define wxComboBox_SetInsertionPointEnd 1591
-#define wxComboBox_SetSelection_1 1592
-#define wxComboBox_SetSelection_2 1593
-#define wxComboBox_SetValue 1594
-#define wxComboBox_Undo 1595
-#define wxGauge_new_0 1596
-#define wxGauge_new_4 1597
-#define wxGauge_Create 1598
-#define wxGauge_GetBezelFace 1599
-#define wxGauge_GetRange 1600
-#define wxGauge_GetShadowWidth 1601
-#define wxGauge_GetValue 1602
-#define wxGauge_IsVertical 1603
-#define wxGauge_SetBezelFace 1604
-#define wxGauge_SetRange 1605
-#define wxGauge_SetShadowWidth 1606
-#define wxGauge_SetValue 1607
-#define wxGauge_Pulse 1608
-#define wxGauge_destroy 1609
-#define wxGenericDirCtrl_new_0 1610
-#define wxGenericDirCtrl_new_2 1611
-#define wxGenericDirCtrl_destruct 1612
-#define wxGenericDirCtrl_Create 1613
-#define wxGenericDirCtrl_Init 1614
-#define wxGenericDirCtrl_CollapseTree 1615
-#define wxGenericDirCtrl_ExpandPath 1616
-#define wxGenericDirCtrl_GetDefaultPath 1617
-#define wxGenericDirCtrl_GetPath 1618
-#define wxGenericDirCtrl_GetFilePath 1619
-#define wxGenericDirCtrl_GetFilter 1620
-#define wxGenericDirCtrl_GetFilterIndex 1621
-#define wxGenericDirCtrl_GetRootId 1622
-#define wxGenericDirCtrl_GetTreeCtrl 1623
-#define wxGenericDirCtrl_ReCreateTree 1624
-#define wxGenericDirCtrl_SetDefaultPath 1625
-#define wxGenericDirCtrl_SetFilter 1626
-#define wxGenericDirCtrl_SetFilterIndex 1627
-#define wxGenericDirCtrl_SetPath 1628
-#define wxStaticBox_new_4 1630
-#define wxStaticBox_new_0 1631
-#define wxStaticBox_Create 1632
-#define wxStaticBox_destroy 1633
-#define wxStaticLine_new_2 1635
-#define wxStaticLine_new_0 1636
-#define wxStaticLine_Create 1637
-#define wxStaticLine_IsVertical 1638
-#define wxStaticLine_GetDefaultSize 1639
-#define wxStaticLine_destroy 1640
-#define wxListBox_new_3 1643
-#define wxListBox_new_0 1644
-#define wxListBox_destruct 1646
-#define wxListBox_Create 1648
-#define wxListBox_Deselect 1649
-#define wxListBox_GetSelections 1650
-#define wxListBox_InsertItems 1651
-#define wxListBox_IsSelected 1652
-#define wxListBox_Set 1653
-#define wxListBox_HitTest 1654
-#define wxListBox_SetFirstItem_1_0 1655
-#define wxListBox_SetFirstItem_1_1 1656
-#define wxListCtrl_new_0 1657
-#define wxListCtrl_new_2 1658
-#define wxListCtrl_Arrange 1659
-#define wxListCtrl_AssignImageList 1660
-#define wxListCtrl_ClearAll 1661
-#define wxListCtrl_Create 1662
-#define wxListCtrl_DeleteAllItems 1663
-#define wxListCtrl_DeleteColumn 1664
-#define wxListCtrl_DeleteItem 1665
-#define wxListCtrl_EditLabel 1666
-#define wxListCtrl_EnsureVisible 1667
-#define wxListCtrl_FindItem_3_0 1668
-#define wxListCtrl_FindItem_3_1 1669
-#define wxListCtrl_GetColumn 1670
-#define wxListCtrl_GetColumnCount 1671
-#define wxListCtrl_GetColumnWidth 1672
-#define wxListCtrl_GetCountPerPage 1673
-#define wxListCtrl_GetEditControl 1674
-#define wxListCtrl_GetImageList 1675
-#define wxListCtrl_GetItem 1676
-#define wxListCtrl_GetItemBackgroundColour 1677
-#define wxListCtrl_GetItemCount 1678
-#define wxListCtrl_GetItemData 1679
-#define wxListCtrl_GetItemFont 1680
-#define wxListCtrl_GetItemPosition 1681
-#define wxListCtrl_GetItemRect 1682
-#define wxListCtrl_GetItemSpacing 1683
-#define wxListCtrl_GetItemState 1684
-#define wxListCtrl_GetItemText 1685
-#define wxListCtrl_GetItemTextColour 1686
-#define wxListCtrl_GetNextItem 1687
-#define wxListCtrl_GetSelectedItemCount 1688
-#define wxListCtrl_GetTextColour 1689
-#define wxListCtrl_GetTopItem 1690
-#define wxListCtrl_GetViewRect 1691
-#define wxListCtrl_HitTest 1692
-#define wxListCtrl_InsertColumn_2 1693
-#define wxListCtrl_InsertColumn_3 1694
-#define wxListCtrl_InsertItem_1 1695
-#define wxListCtrl_InsertItem_2_1 1696
-#define wxListCtrl_InsertItem_2_0 1697
-#define wxListCtrl_InsertItem_3 1698
-#define wxListCtrl_RefreshItem 1699
-#define wxListCtrl_RefreshItems 1700
-#define wxListCtrl_ScrollList 1701
-#define wxListCtrl_SetBackgroundColour 1702
-#define wxListCtrl_SetColumn 1703
-#define wxListCtrl_SetColumnWidth 1704
-#define wxListCtrl_SetImageList 1705
-#define wxListCtrl_SetItem_1 1706
-#define wxListCtrl_SetItem_4 1707
-#define wxListCtrl_SetItemBackgroundColour 1708
-#define wxListCtrl_SetItemCount 1709
-#define wxListCtrl_SetItemData 1710
-#define wxListCtrl_SetItemFont 1711
-#define wxListCtrl_SetItemImage 1712
-#define wxListCtrl_SetItemColumnImage 1713
-#define wxListCtrl_SetItemPosition 1714
-#define wxListCtrl_SetItemState 1715
-#define wxListCtrl_SetItemText 1716
-#define wxListCtrl_SetItemTextColour 1717
-#define wxListCtrl_SetSingleStyle 1718
-#define wxListCtrl_SetTextColour 1719
-#define wxListCtrl_SetWindowStyleFlag 1720
-#define wxListCtrl_SortItems 1721
-#define wxListCtrl_destroy 1722
-#define wxListView_ClearColumnImage 1723
-#define wxListView_Focus 1724
-#define wxListView_GetFirstSelected 1725
-#define wxListView_GetFocusedItem 1726
-#define wxListView_GetNextSelected 1727
-#define wxListView_IsSelected 1728
-#define wxListView_Select 1729
-#define wxListView_SetColumnImage 1730
-#define wxListItem_new_0 1731
-#define wxListItem_new_1 1732
-#define wxListItem_destruct 1733
-#define wxListItem_Clear 1734
-#define wxListItem_GetAlign 1735
-#define wxListItem_GetBackgroundColour 1736
-#define wxListItem_GetColumn 1737
-#define wxListItem_GetFont 1738
-#define wxListItem_GetId 1739
-#define wxListItem_GetImage 1740
-#define wxListItem_GetMask 1741
-#define wxListItem_GetState 1742
-#define wxListItem_GetText 1743
-#define wxListItem_GetTextColour 1744
-#define wxListItem_GetWidth 1745
-#define wxListItem_SetAlign 1746
-#define wxListItem_SetBackgroundColour 1747
-#define wxListItem_SetColumn 1748
-#define wxListItem_SetFont 1749
-#define wxListItem_SetId 1750
-#define wxListItem_SetImage 1751
-#define wxListItem_SetMask 1752
-#define wxListItem_SetState 1753
-#define wxListItem_SetStateMask 1754
-#define wxListItem_SetText 1755
-#define wxListItem_SetTextColour 1756
-#define wxListItem_SetWidth 1757
-#define wxListItemAttr_new_0 1758
-#define wxListItemAttr_new_3 1759
-#define wxListItemAttr_GetBackgroundColour 1760
-#define wxListItemAttr_GetFont 1761
-#define wxListItemAttr_GetTextColour 1762
-#define wxListItemAttr_HasBackgroundColour 1763
-#define wxListItemAttr_HasFont 1764
-#define wxListItemAttr_HasTextColour 1765
-#define wxListItemAttr_SetBackgroundColour 1766
-#define wxListItemAttr_SetFont 1767
-#define wxListItemAttr_SetTextColour 1768
-#define wxListItemAttr_destroy 1769
-#define wxImageList_new_0 1770
-#define wxImageList_new_3 1771
-#define wxImageList_Add_1 1772
-#define wxImageList_Add_2_0 1773
-#define wxImageList_Add_2_1 1774
-#define wxImageList_Create 1775
-#define wxImageList_Draw 1777
-#define wxImageList_GetBitmap 1778
-#define wxImageList_GetIcon 1779
-#define wxImageList_GetImageCount 1780
-#define wxImageList_GetSize 1781
-#define wxImageList_Remove 1782
-#define wxImageList_RemoveAll 1783
-#define wxImageList_Replace_2 1784
-#define wxImageList_Replace_3 1785
-#define wxImageList_destroy 1786
-#define wxTextAttr_new_0 1787
-#define wxTextAttr_new_2 1788
-#define wxTextAttr_GetAlignment 1789
-#define wxTextAttr_GetBackgroundColour 1790
-#define wxTextAttr_GetFont 1791
-#define wxTextAttr_GetLeftIndent 1792
-#define wxTextAttr_GetLeftSubIndent 1793
-#define wxTextAttr_GetRightIndent 1794
-#define wxTextAttr_GetTabs 1795
-#define wxTextAttr_GetTextColour 1796
-#define wxTextAttr_HasBackgroundColour 1797
-#define wxTextAttr_HasFont 1798
-#define wxTextAttr_HasTextColour 1799
-#define wxTextAttr_GetFlags 1800
-#define wxTextAttr_IsDefault 1801
-#define wxTextAttr_SetAlignment 1802
-#define wxTextAttr_SetBackgroundColour 1803
-#define wxTextAttr_SetFlags 1804
-#define wxTextAttr_SetFont 1805
-#define wxTextAttr_SetLeftIndent 1806
-#define wxTextAttr_SetRightIndent 1807
-#define wxTextAttr_SetTabs 1808
-#define wxTextAttr_SetTextColour 1809
-#define wxTextAttr_destroy 1810
-#define wxTextCtrl_new_3 1812
-#define wxTextCtrl_new_0 1813
-#define wxTextCtrl_destruct 1815
-#define wxTextCtrl_AppendText 1816
-#define wxTextCtrl_CanCopy 1817
-#define wxTextCtrl_CanCut 1818
-#define wxTextCtrl_CanPaste 1819
-#define wxTextCtrl_CanRedo 1820
-#define wxTextCtrl_CanUndo 1821
-#define wxTextCtrl_Clear 1822
-#define wxTextCtrl_Copy 1823
-#define wxTextCtrl_Create 1824
-#define wxTextCtrl_Cut 1825
-#define wxTextCtrl_DiscardEdits 1826
-#define wxTextCtrl_ChangeValue 1827
-#define wxTextCtrl_EmulateKeyPress 1828
-#define wxTextCtrl_GetDefaultStyle 1829
-#define wxTextCtrl_GetInsertionPoint 1830
-#define wxTextCtrl_GetLastPosition 1831
-#define wxTextCtrl_GetLineLength 1832
-#define wxTextCtrl_GetLineText 1833
-#define wxTextCtrl_GetNumberOfLines 1834
-#define wxTextCtrl_GetRange 1835
-#define wxTextCtrl_GetSelection 1836
-#define wxTextCtrl_GetStringSelection 1837
-#define wxTextCtrl_GetStyle 1838
-#define wxTextCtrl_GetValue 1839
-#define wxTextCtrl_IsEditable 1840
-#define wxTextCtrl_IsModified 1841
-#define wxTextCtrl_IsMultiLine 1842
-#define wxTextCtrl_IsSingleLine 1843
-#define wxTextCtrl_LoadFile 1844
-#define wxTextCtrl_MarkDirty 1845
-#define wxTextCtrl_Paste 1846
-#define wxTextCtrl_PositionToXY 1847
-#define wxTextCtrl_Redo 1848
-#define wxTextCtrl_Remove 1849
-#define wxTextCtrl_Replace 1850
-#define wxTextCtrl_SaveFile 1851
-#define wxTextCtrl_SetDefaultStyle 1852
-#define wxTextCtrl_SetEditable 1853
-#define wxTextCtrl_SetInsertionPoint 1854
-#define wxTextCtrl_SetInsertionPointEnd 1855
-#define wxTextCtrl_SetMaxLength 1857
-#define wxTextCtrl_SetSelection 1858
-#define wxTextCtrl_SetStyle 1859
-#define wxTextCtrl_SetValue 1860
-#define wxTextCtrl_ShowPosition 1861
-#define wxTextCtrl_Undo 1862
-#define wxTextCtrl_WriteText 1863
-#define wxTextCtrl_XYToPosition 1864
-#define wxNotebook_new_0 1867
-#define wxNotebook_new_3 1868
-#define wxNotebook_destruct 1869
-#define wxNotebook_AddPage 1870
-#define wxNotebook_AdvanceSelection 1871
-#define wxNotebook_AssignImageList 1872
-#define wxNotebook_Create 1873
-#define wxNotebook_DeleteAllPages 1874
-#define wxNotebook_DeletePage 1875
-#define wxNotebook_RemovePage 1876
-#define wxNotebook_GetCurrentPage 1877
-#define wxNotebook_GetImageList 1878
-#define wxNotebook_GetPage 1880
-#define wxNotebook_GetPageCount 1881
-#define wxNotebook_GetPageImage 1882
-#define wxNotebook_GetPageText 1883
-#define wxNotebook_GetRowCount 1884
-#define wxNotebook_GetSelection 1885
-#define wxNotebook_GetThemeBackgroundColour 1886
-#define wxNotebook_HitTest 1888
-#define wxNotebook_InsertPage 1890
-#define wxNotebook_SetImageList 1891
-#define wxNotebook_SetPadding 1892
-#define wxNotebook_SetPageSize 1893
-#define wxNotebook_SetPageImage 1894
-#define wxNotebook_SetPageText 1895
-#define wxNotebook_SetSelection 1896
-#define wxNotebook_ChangeSelection 1897
-#define wxChoicebook_new_0 1898
-#define wxChoicebook_new_3 1899
-#define wxChoicebook_AddPage 1900
-#define wxChoicebook_AdvanceSelection 1901
-#define wxChoicebook_AssignImageList 1902
-#define wxChoicebook_Create 1903
-#define wxChoicebook_DeleteAllPages 1904
-#define wxChoicebook_DeletePage 1905
-#define wxChoicebook_RemovePage 1906
-#define wxChoicebook_GetCurrentPage 1907
-#define wxChoicebook_GetImageList 1908
-#define wxChoicebook_GetPage 1910
-#define wxChoicebook_GetPageCount 1911
-#define wxChoicebook_GetPageImage 1912
-#define wxChoicebook_GetPageText 1913
-#define wxChoicebook_GetSelection 1914
-#define wxChoicebook_HitTest 1915
-#define wxChoicebook_InsertPage 1916
-#define wxChoicebook_SetImageList 1917
-#define wxChoicebook_SetPageSize 1918
-#define wxChoicebook_SetPageImage 1919
-#define wxChoicebook_SetPageText 1920
-#define wxChoicebook_SetSelection 1921
-#define wxChoicebook_ChangeSelection 1922
-#define wxChoicebook_destroy 1923
-#define wxToolbook_new_0 1924
-#define wxToolbook_new_3 1925
-#define wxToolbook_AddPage 1926
-#define wxToolbook_AdvanceSelection 1927
-#define wxToolbook_AssignImageList 1928
-#define wxToolbook_Create 1929
-#define wxToolbook_DeleteAllPages 1930
-#define wxToolbook_DeletePage 1931
-#define wxToolbook_RemovePage 1932
-#define wxToolbook_GetCurrentPage 1933
-#define wxToolbook_GetImageList 1934
-#define wxToolbook_GetPage 1936
-#define wxToolbook_GetPageCount 1937
-#define wxToolbook_GetPageImage 1938
-#define wxToolbook_GetPageText 1939
-#define wxToolbook_GetSelection 1940
-#define wxToolbook_HitTest 1942
-#define wxToolbook_InsertPage 1943
-#define wxToolbook_SetImageList 1944
-#define wxToolbook_SetPageSize 1945
-#define wxToolbook_SetPageImage 1946
-#define wxToolbook_SetPageText 1947
-#define wxToolbook_SetSelection 1948
-#define wxToolbook_ChangeSelection 1949
-#define wxToolbook_destroy 1950
-#define wxListbook_new_0 1951
-#define wxListbook_new_3 1952
-#define wxListbook_AddPage 1953
-#define wxListbook_AdvanceSelection 1954
-#define wxListbook_AssignImageList 1955
-#define wxListbook_Create 1956
-#define wxListbook_DeleteAllPages 1957
-#define wxListbook_DeletePage 1958
-#define wxListbook_RemovePage 1959
-#define wxListbook_GetCurrentPage 1960
-#define wxListbook_GetImageList 1961
-#define wxListbook_GetPage 1963
-#define wxListbook_GetPageCount 1964
-#define wxListbook_GetPageImage 1965
-#define wxListbook_GetPageText 1966
-#define wxListbook_GetSelection 1967
-#define wxListbook_HitTest 1969
-#define wxListbook_InsertPage 1970
-#define wxListbook_SetImageList 1971
-#define wxListbook_SetPageSize 1972
-#define wxListbook_SetPageImage 1973
-#define wxListbook_SetPageText 1974
-#define wxListbook_SetSelection 1975
-#define wxListbook_ChangeSelection 1976
-#define wxListbook_destroy 1977
-#define wxTreebook_new_0 1978
-#define wxTreebook_new_3 1979
-#define wxTreebook_AddPage 1980
-#define wxTreebook_AdvanceSelection 1981
-#define wxTreebook_AssignImageList 1982
-#define wxTreebook_Create 1983
-#define wxTreebook_DeleteAllPages 1984
-#define wxTreebook_DeletePage 1985
-#define wxTreebook_RemovePage 1986
-#define wxTreebook_GetCurrentPage 1987
-#define wxTreebook_GetImageList 1988
-#define wxTreebook_GetPage 1990
-#define wxTreebook_GetPageCount 1991
-#define wxTreebook_GetPageImage 1992
-#define wxTreebook_GetPageText 1993
-#define wxTreebook_GetSelection 1994
-#define wxTreebook_ExpandNode 1995
-#define wxTreebook_IsNodeExpanded 1996
-#define wxTreebook_HitTest 1998
-#define wxTreebook_InsertPage 1999
-#define wxTreebook_InsertSubPage 2000
-#define wxTreebook_SetImageList 2001
-#define wxTreebook_SetPageSize 2002
-#define wxTreebook_SetPageImage 2003
-#define wxTreebook_SetPageText 2004
-#define wxTreebook_SetSelection 2005
-#define wxTreebook_ChangeSelection 2006
-#define wxTreebook_destroy 2007
-#define wxTreeCtrl_new_2 2010
-#define wxTreeCtrl_new_0 2011
-#define wxTreeCtrl_destruct 2013
-#define wxTreeCtrl_AddRoot 2014
-#define wxTreeCtrl_AppendItem 2015
-#define wxTreeCtrl_AssignImageList 2016
-#define wxTreeCtrl_AssignStateImageList 2017
-#define wxTreeCtrl_Collapse 2018
-#define wxTreeCtrl_CollapseAndReset 2019
-#define wxTreeCtrl_Create 2020
-#define wxTreeCtrl_Delete 2021
-#define wxTreeCtrl_DeleteAllItems 2022
-#define wxTreeCtrl_DeleteChildren 2023
-#define wxTreeCtrl_EditLabel 2024
-#define wxTreeCtrl_EnsureVisible 2025
-#define wxTreeCtrl_Expand 2026
-#define wxTreeCtrl_GetBoundingRect 2027
-#define wxTreeCtrl_GetChildrenCount 2029
-#define wxTreeCtrl_GetCount 2030
-#define wxTreeCtrl_GetEditControl 2031
-#define wxTreeCtrl_GetFirstChild 2032
-#define wxTreeCtrl_GetNextChild 2033
-#define wxTreeCtrl_GetFirstVisibleItem 2034
-#define wxTreeCtrl_GetImageList 2035
-#define wxTreeCtrl_GetIndent 2036
-#define wxTreeCtrl_GetItemBackgroundColour 2037
-#define wxTreeCtrl_GetItemData 2038
-#define wxTreeCtrl_GetItemFont 2039
-#define wxTreeCtrl_GetItemImage_1 2040
-#define wxTreeCtrl_GetItemImage_2 2041
-#define wxTreeCtrl_GetItemText 2042
-#define wxTreeCtrl_GetItemTextColour 2043
-#define wxTreeCtrl_GetLastChild 2044
-#define wxTreeCtrl_GetNextSibling 2045
-#define wxTreeCtrl_GetNextVisible 2046
-#define wxTreeCtrl_GetItemParent 2047
-#define wxTreeCtrl_GetPrevSibling 2048
-#define wxTreeCtrl_GetPrevVisible 2049
-#define wxTreeCtrl_GetRootItem 2050
-#define wxTreeCtrl_GetSelection 2051
-#define wxTreeCtrl_GetSelections 2052
-#define wxTreeCtrl_GetStateImageList 2053
-#define wxTreeCtrl_HitTest 2054
-#define wxTreeCtrl_InsertItem 2056
-#define wxTreeCtrl_IsBold 2057
-#define wxTreeCtrl_IsExpanded 2058
-#define wxTreeCtrl_IsSelected 2059
-#define wxTreeCtrl_IsVisible 2060
-#define wxTreeCtrl_ItemHasChildren 2061
-#define wxTreeCtrl_IsTreeItemIdOk 2062
-#define wxTreeCtrl_PrependItem 2063
-#define wxTreeCtrl_ScrollTo 2064
-#define wxTreeCtrl_SelectItem_1 2065
-#define wxTreeCtrl_SelectItem_2 2066
-#define wxTreeCtrl_SetIndent 2067
-#define wxTreeCtrl_SetImageList 2068
-#define wxTreeCtrl_SetItemBackgroundColour 2069
-#define wxTreeCtrl_SetItemBold 2070
-#define wxTreeCtrl_SetItemData 2071
-#define wxTreeCtrl_SetItemDropHighlight 2072
-#define wxTreeCtrl_SetItemFont 2073
-#define wxTreeCtrl_SetItemHasChildren 2074
-#define wxTreeCtrl_SetItemImage_2 2075
-#define wxTreeCtrl_SetItemImage_3 2076
-#define wxTreeCtrl_SetItemText 2077
-#define wxTreeCtrl_SetItemTextColour 2078
-#define wxTreeCtrl_SetStateImageList 2079
-#define wxTreeCtrl_SetWindowStyle 2080
-#define wxTreeCtrl_SortChildren 2081
-#define wxTreeCtrl_Toggle 2082
-#define wxTreeCtrl_ToggleItemSelection 2083
-#define wxTreeCtrl_Unselect 2084
-#define wxTreeCtrl_UnselectAll 2085
-#define wxTreeCtrl_UnselectItem 2086
-#define wxScrollBar_new_0 2087
-#define wxScrollBar_new_3 2088
-#define wxScrollBar_destruct 2089
-#define wxScrollBar_Create 2090
-#define wxScrollBar_GetRange 2091
-#define wxScrollBar_GetPageSize 2092
-#define wxScrollBar_GetThumbPosition 2093
-#define wxScrollBar_GetThumbSize 2094
-#define wxScrollBar_SetThumbPosition 2095
-#define wxScrollBar_SetScrollbar 2096
-#define wxSpinButton_new_2 2098
-#define wxSpinButton_new_0 2099
-#define wxSpinButton_Create 2100
-#define wxSpinButton_GetMax 2101
-#define wxSpinButton_GetMin 2102
-#define wxSpinButton_GetValue 2103
-#define wxSpinButton_SetRange 2104
-#define wxSpinButton_SetValue 2105
-#define wxSpinButton_destroy 2106
-#define wxSpinCtrl_new_0 2107
-#define wxSpinCtrl_new_2 2108
-#define wxSpinCtrl_Create 2110
-#define wxSpinCtrl_SetValue_1_1 2113
-#define wxSpinCtrl_SetValue_1_0 2114
-#define wxSpinCtrl_GetValue 2116
-#define wxSpinCtrl_SetRange 2118
-#define wxSpinCtrl_SetSelection 2119
-#define wxSpinCtrl_GetMin 2121
-#define wxSpinCtrl_GetMax 2123
-#define wxSpinCtrl_destroy 2124
-#define wxStaticText_new_0 2125
-#define wxStaticText_new_4 2126
-#define wxStaticText_Create 2127
-#define wxStaticText_GetLabel 2128
-#define wxStaticText_SetLabel 2129
-#define wxStaticText_Wrap 2130
-#define wxStaticText_destroy 2131
-#define wxStaticBitmap_new_0 2132
-#define wxStaticBitmap_new_4 2133
-#define wxStaticBitmap_Create 2134
-#define wxStaticBitmap_GetBitmap 2135
-#define wxStaticBitmap_SetBitmap 2136
-#define wxStaticBitmap_destroy 2137
-#define wxRadioBox_new 2138
-#define wxRadioBox_destruct 2140
-#define wxRadioBox_Create 2141
-#define wxRadioBox_Enable_2 2142
-#define wxRadioBox_Enable_1 2143
-#define wxRadioBox_GetSelection 2144
-#define wxRadioBox_GetString 2145
-#define wxRadioBox_SetSelection 2146
-#define wxRadioBox_Show_2 2147
-#define wxRadioBox_Show_1 2148
-#define wxRadioBox_GetColumnCount 2149
-#define wxRadioBox_GetItemHelpText 2150
-#define wxRadioBox_GetItemToolTip 2151
-#define wxRadioBox_GetItemFromPoint 2153
-#define wxRadioBox_GetRowCount 2154
-#define wxRadioBox_IsItemEnabled 2155
-#define wxRadioBox_IsItemShown 2156
-#define wxRadioBox_SetItemHelpText 2157
-#define wxRadioBox_SetItemToolTip 2158
-#define wxRadioButton_new_0 2159
-#define wxRadioButton_new_4 2160
-#define wxRadioButton_Create 2161
-#define wxRadioButton_GetValue 2162
-#define wxRadioButton_SetValue 2163
-#define wxRadioButton_destroy 2164
-#define wxSlider_new_6 2166
-#define wxSlider_new_0 2167
-#define wxSlider_Create 2168
-#define wxSlider_GetLineSize 2169
-#define wxSlider_GetMax 2170
-#define wxSlider_GetMin 2171
-#define wxSlider_GetPageSize 2172
-#define wxSlider_GetThumbLength 2173
-#define wxSlider_GetValue 2174
-#define wxSlider_SetLineSize 2175
-#define wxSlider_SetPageSize 2176
-#define wxSlider_SetRange 2177
-#define wxSlider_SetThumbLength 2178
-#define wxSlider_SetValue 2179
-#define wxSlider_destroy 2180
-#define wxDialog_new_4 2182
-#define wxDialog_new_0 2183
-#define wxDialog_destruct 2185
-#define wxDialog_Create 2186
-#define wxDialog_CreateButtonSizer 2187
-#define wxDialog_CreateStdDialogButtonSizer 2188
-#define wxDialog_EndModal 2189
-#define wxDialog_GetAffirmativeId 2190
-#define wxDialog_GetReturnCode 2191
-#define wxDialog_IsModal 2192
-#define wxDialog_SetAffirmativeId 2193
-#define wxDialog_SetReturnCode 2194
-#define wxDialog_Show 2195
-#define wxDialog_ShowModal 2196
-#define wxColourDialog_new_0 2197
-#define wxColourDialog_new_2 2198
-#define wxColourDialog_destruct 2199
-#define wxColourDialog_Create 2200
-#define wxColourDialog_GetColourData 2201
-#define wxColourData_new_0 2202
-#define wxColourData_new_1 2203
-#define wxColourData_destruct 2204
-#define wxColourData_GetChooseFull 2205
-#define wxColourData_GetColour 2206
-#define wxColourData_GetCustomColour 2208
-#define wxColourData_SetChooseFull 2209
-#define wxColourData_SetColour 2210
-#define wxColourData_SetCustomColour 2211
-#define wxPalette_new_0 2212
-#define wxPalette_new_4 2213
-#define wxPalette_destruct 2215
-#define wxPalette_Create 2216
-#define wxPalette_GetColoursCount 2217
-#define wxPalette_GetPixel 2218
-#define wxPalette_GetRGB 2219
-#define wxPalette_IsOk 2220
-#define wxDirDialog_new 2224
-#define wxDirDialog_destruct 2225
-#define wxDirDialog_GetPath 2226
-#define wxDirDialog_GetMessage 2227
-#define wxDirDialog_SetMessage 2228
-#define wxDirDialog_SetPath 2229
-#define wxFileDialog_new 2233
-#define wxFileDialog_destruct 2234
-#define wxFileDialog_GetDirectory 2235
-#define wxFileDialog_GetFilename 2236
-#define wxFileDialog_GetFilenames 2237
-#define wxFileDialog_GetFilterIndex 2238
-#define wxFileDialog_GetMessage 2239
-#define wxFileDialog_GetPath 2240
-#define wxFileDialog_GetPaths 2241
-#define wxFileDialog_GetWildcard 2242
-#define wxFileDialog_SetDirectory 2243
-#define wxFileDialog_SetFilename 2244
-#define wxFileDialog_SetFilterIndex 2245
-#define wxFileDialog_SetMessage 2246
-#define wxFileDialog_SetPath 2247
-#define wxFileDialog_SetWildcard 2248
-#define wxPickerBase_SetInternalMargin 2249
-#define wxPickerBase_GetInternalMargin 2250
-#define wxPickerBase_SetTextCtrlProportion 2251
-#define wxPickerBase_SetPickerCtrlProportion 2252
-#define wxPickerBase_GetTextCtrlProportion 2253
-#define wxPickerBase_GetPickerCtrlProportion 2254
-#define wxPickerBase_HasTextCtrl 2255
-#define wxPickerBase_GetTextCtrl 2256
-#define wxPickerBase_IsTextCtrlGrowable 2257
-#define wxPickerBase_SetPickerCtrlGrowable 2258
-#define wxPickerBase_SetTextCtrlGrowable 2259
-#define wxPickerBase_IsPickerCtrlGrowable 2260
-#define wxFilePickerCtrl_new_0 2261
-#define wxFilePickerCtrl_new_3 2262
-#define wxFilePickerCtrl_Create 2263
-#define wxFilePickerCtrl_GetPath 2264
-#define wxFilePickerCtrl_SetPath 2265
-#define wxFilePickerCtrl_destroy 2266
-#define wxDirPickerCtrl_new_0 2267
-#define wxDirPickerCtrl_new_3 2268
-#define wxDirPickerCtrl_Create 2269
-#define wxDirPickerCtrl_GetPath 2270
-#define wxDirPickerCtrl_SetPath 2271
-#define wxDirPickerCtrl_destroy 2272
-#define wxColourPickerCtrl_new_0 2273
-#define wxColourPickerCtrl_new_3 2274
-#define wxColourPickerCtrl_Create 2275
-#define wxColourPickerCtrl_GetColour 2276
-#define wxColourPickerCtrl_SetColour_1_1 2277
-#define wxColourPickerCtrl_SetColour_1_0 2278
-#define wxColourPickerCtrl_destroy 2279
-#define wxDatePickerCtrl_new_0 2280
-#define wxDatePickerCtrl_new_3 2281
-#define wxDatePickerCtrl_GetRange 2282
-#define wxDatePickerCtrl_GetValue 2283
-#define wxDatePickerCtrl_SetRange 2284
-#define wxDatePickerCtrl_SetValue 2285
-#define wxDatePickerCtrl_destroy 2286
-#define wxFontPickerCtrl_new_0 2287
-#define wxFontPickerCtrl_new_3 2288
-#define wxFontPickerCtrl_Create 2289
-#define wxFontPickerCtrl_GetSelectedFont 2290
-#define wxFontPickerCtrl_SetSelectedFont 2291
-#define wxFontPickerCtrl_GetMaxPointSize 2292
-#define wxFontPickerCtrl_SetMaxPointSize 2293
-#define wxFontPickerCtrl_destroy 2294
-#define wxFindReplaceDialog_new_0 2297
-#define wxFindReplaceDialog_new_4 2298
-#define wxFindReplaceDialog_destruct 2299
-#define wxFindReplaceDialog_Create 2300
-#define wxFindReplaceDialog_GetData 2301
-#define wxFindReplaceData_new_0 2302
-#define wxFindReplaceData_new_1 2303
-#define wxFindReplaceData_GetFindString 2304
-#define wxFindReplaceData_GetReplaceString 2305
-#define wxFindReplaceData_GetFlags 2306
-#define wxFindReplaceData_SetFlags 2307
-#define wxFindReplaceData_SetFindString 2308
-#define wxFindReplaceData_SetReplaceString 2309
-#define wxFindReplaceData_destroy 2310
-#define wxMultiChoiceDialog_new_0 2311
-#define wxMultiChoiceDialog_new_5 2313
-#define wxMultiChoiceDialog_GetSelections 2314
-#define wxMultiChoiceDialog_SetSelections 2315
-#define wxMultiChoiceDialog_destroy 2316
-#define wxSingleChoiceDialog_new_0 2317
-#define wxSingleChoiceDialog_new_5 2319
-#define wxSingleChoiceDialog_GetSelection 2320
-#define wxSingleChoiceDialog_GetStringSelection 2321
-#define wxSingleChoiceDialog_SetSelection 2322
-#define wxSingleChoiceDialog_destroy 2323
-#define wxTextEntryDialog_new 2324
-#define wxTextEntryDialog_GetValue 2325
-#define wxTextEntryDialog_SetValue 2326
-#define wxTextEntryDialog_destroy 2327
-#define wxPasswordEntryDialog_new 2328
-#define wxPasswordEntryDialog_destroy 2329
-#define wxFontData_new_0 2330
-#define wxFontData_new_1 2331
-#define wxFontData_destruct 2332
-#define wxFontData_EnableEffects 2333
-#define wxFontData_GetAllowSymbols 2334
-#define wxFontData_GetColour 2335
-#define wxFontData_GetChosenFont 2336
-#define wxFontData_GetEnableEffects 2337
-#define wxFontData_GetInitialFont 2338
-#define wxFontData_GetShowHelp 2339
-#define wxFontData_SetAllowSymbols 2340
-#define wxFontData_SetChosenFont 2341
-#define wxFontData_SetColour 2342
-#define wxFontData_SetInitialFont 2343
-#define wxFontData_SetRange 2344
-#define wxFontData_SetShowHelp 2345
-#define wxFontDialog_new_0 2349
-#define wxFontDialog_new_2 2351
-#define wxFontDialog_Create 2353
-#define wxFontDialog_GetFontData 2354
-#define wxFontDialog_destroy 2356
-#define wxProgressDialog_new 2357
-#define wxProgressDialog_destruct 2358
-#define wxProgressDialog_Resume 2359
-#define wxProgressDialog_Update_2 2360
-#define wxProgressDialog_Update_0 2361
-#define wxMessageDialog_new 2362
-#define wxMessageDialog_destruct 2363
-#define wxPageSetupDialog_new 2364
-#define wxPageSetupDialog_destruct 2365
-#define wxPageSetupDialog_GetPageSetupData 2366
-#define wxPageSetupDialog_ShowModal 2367
-#define wxPageSetupDialogData_new_0 2368
-#define wxPageSetupDialogData_new_1_0 2369
-#define wxPageSetupDialogData_new_1_1 2370
-#define wxPageSetupDialogData_destruct 2371
-#define wxPageSetupDialogData_EnableHelp 2372
-#define wxPageSetupDialogData_EnableMargins 2373
-#define wxPageSetupDialogData_EnableOrientation 2374
-#define wxPageSetupDialogData_EnablePaper 2375
-#define wxPageSetupDialogData_EnablePrinter 2376
-#define wxPageSetupDialogData_GetDefaultMinMargins 2377
-#define wxPageSetupDialogData_GetEnableMargins 2378
-#define wxPageSetupDialogData_GetEnableOrientation 2379
-#define wxPageSetupDialogData_GetEnablePaper 2380
-#define wxPageSetupDialogData_GetEnablePrinter 2381
-#define wxPageSetupDialogData_GetEnableHelp 2382
-#define wxPageSetupDialogData_GetDefaultInfo 2383
-#define wxPageSetupDialogData_GetMarginTopLeft 2384
-#define wxPageSetupDialogData_GetMarginBottomRight 2385
-#define wxPageSetupDialogData_GetMinMarginTopLeft 2386
-#define wxPageSetupDialogData_GetMinMarginBottomRight 2387
-#define wxPageSetupDialogData_GetPaperId 2388
-#define wxPageSetupDialogData_GetPaperSize 2389
-#define wxPageSetupDialogData_GetPrintData 2391
-#define wxPageSetupDialogData_IsOk 2392
-#define wxPageSetupDialogData_SetDefaultInfo 2393
-#define wxPageSetupDialogData_SetDefaultMinMargins 2394
-#define wxPageSetupDialogData_SetMarginTopLeft 2395
-#define wxPageSetupDialogData_SetMarginBottomRight 2396
-#define wxPageSetupDialogData_SetMinMarginTopLeft 2397
-#define wxPageSetupDialogData_SetMinMarginBottomRight 2398
-#define wxPageSetupDialogData_SetPaperId 2399
-#define wxPageSetupDialogData_SetPaperSize_1_1 2400
-#define wxPageSetupDialogData_SetPaperSize_1_0 2401
-#define wxPageSetupDialogData_SetPrintData 2402
-#define wxPrintDialog_new_2_0 2403
-#define wxPrintDialog_new_2_1 2404
-#define wxPrintDialog_destruct 2405
-#define wxPrintDialog_GetPrintDialogData 2406
-#define wxPrintDialog_GetPrintDC 2407
-#define wxPrintDialogData_new_0 2408
-#define wxPrintDialogData_new_1_1 2409
-#define wxPrintDialogData_new_1_0 2410
-#define wxPrintDialogData_destruct 2411
-#define wxPrintDialogData_EnableHelp 2412
-#define wxPrintDialogData_EnablePageNumbers 2413
-#define wxPrintDialogData_EnablePrintToFile 2414
-#define wxPrintDialogData_EnableSelection 2415
-#define wxPrintDialogData_GetAllPages 2416
-#define wxPrintDialogData_GetCollate 2417
-#define wxPrintDialogData_GetFromPage 2418
-#define wxPrintDialogData_GetMaxPage 2419
-#define wxPrintDialogData_GetMinPage 2420
-#define wxPrintDialogData_GetNoCopies 2421
-#define wxPrintDialogData_GetPrintData 2422
-#define wxPrintDialogData_GetPrintToFile 2423
-#define wxPrintDialogData_GetSelection 2424
-#define wxPrintDialogData_GetToPage 2425
-#define wxPrintDialogData_IsOk 2426
-#define wxPrintDialogData_SetCollate 2427
-#define wxPrintDialogData_SetFromPage 2428
-#define wxPrintDialogData_SetMaxPage 2429
-#define wxPrintDialogData_SetMinPage 2430
-#define wxPrintDialogData_SetNoCopies 2431
-#define wxPrintDialogData_SetPrintData 2432
-#define wxPrintDialogData_SetPrintToFile 2433
-#define wxPrintDialogData_SetSelection 2434
-#define wxPrintDialogData_SetToPage 2435
-#define wxPrintData_new_0 2436
-#define wxPrintData_new_1 2437
-#define wxPrintData_destruct 2438
-#define wxPrintData_GetCollate 2439
-#define wxPrintData_GetBin 2440
-#define wxPrintData_GetColour 2441
-#define wxPrintData_GetDuplex 2442
-#define wxPrintData_GetNoCopies 2443
-#define wxPrintData_GetOrientation 2444
-#define wxPrintData_GetPaperId 2445
-#define wxPrintData_GetPrinterName 2446
-#define wxPrintData_GetQuality 2447
-#define wxPrintData_IsOk 2448
-#define wxPrintData_SetBin 2449
-#define wxPrintData_SetCollate 2450
-#define wxPrintData_SetColour 2451
-#define wxPrintData_SetDuplex 2452
-#define wxPrintData_SetNoCopies 2453
-#define wxPrintData_SetOrientation 2454
-#define wxPrintData_SetPaperId 2455
-#define wxPrintData_SetPrinterName 2456
-#define wxPrintData_SetQuality 2457
-#define wxPrintPreview_new_2 2460
-#define wxPrintPreview_new_3 2461
-#define wxPrintPreview_destruct 2463
-#define wxPrintPreview_GetCanvas 2464
-#define wxPrintPreview_GetCurrentPage 2465
-#define wxPrintPreview_GetFrame 2466
-#define wxPrintPreview_GetMaxPage 2467
-#define wxPrintPreview_GetMinPage 2468
-#define wxPrintPreview_GetPrintout 2469
-#define wxPrintPreview_GetPrintoutForPrinting 2470
-#define wxPrintPreview_IsOk 2471
-#define wxPrintPreview_PaintPage 2472
-#define wxPrintPreview_Print 2473
-#define wxPrintPreview_RenderPage 2474
-#define wxPrintPreview_SetCanvas 2475
-#define wxPrintPreview_SetCurrentPage 2476
-#define wxPrintPreview_SetFrame 2477
-#define wxPrintPreview_SetPrintout 2478
-#define wxPrintPreview_SetZoom 2479
-#define wxPreviewFrame_new 2480
-#define wxPreviewFrame_destruct 2481
-#define wxPreviewFrame_CreateControlBar 2482
-#define wxPreviewFrame_CreateCanvas 2483
-#define wxPreviewFrame_Initialize 2484
-#define wxPreviewFrame_OnCloseWindow 2485
-#define wxPreviewControlBar_new 2486
-#define wxPreviewControlBar_destruct 2487
-#define wxPreviewControlBar_CreateButtons 2488
-#define wxPreviewControlBar_GetPrintPreview 2489
-#define wxPreviewControlBar_GetZoomControl 2490
-#define wxPreviewControlBar_SetZoomControl 2491
-#define wxPrinter_new 2493
-#define wxPrinter_CreateAbortWindow 2494
-#define wxPrinter_GetAbort 2495
-#define wxPrinter_GetLastError 2496
-#define wxPrinter_GetPrintDialogData 2497
-#define wxPrinter_Print 2498
-#define wxPrinter_PrintDialog 2499
-#define wxPrinter_ReportError 2500
-#define wxPrinter_Setup 2501
-#define wxPrinter_destroy 2502
-#define wxXmlResource_new_1 2503
-#define wxXmlResource_new_2 2504
-#define wxXmlResource_destruct 2505
-#define wxXmlResource_AttachUnknownControl 2506
-#define wxXmlResource_ClearHandlers 2507
-#define wxXmlResource_CompareVersion 2508
-#define wxXmlResource_Get 2509
-#define wxXmlResource_GetFlags 2510
-#define wxXmlResource_GetVersion 2511
-#define wxXmlResource_GetXRCID 2512
-#define wxXmlResource_InitAllHandlers 2513
-#define wxXmlResource_Load 2514
-#define wxXmlResource_LoadBitmap 2515
-#define wxXmlResource_LoadDialog_2 2516
-#define wxXmlResource_LoadDialog_3 2517
-#define wxXmlResource_LoadFrame_2 2518
-#define wxXmlResource_LoadFrame_3 2519
-#define wxXmlResource_LoadIcon 2520
-#define wxXmlResource_LoadMenu 2521
-#define wxXmlResource_LoadMenuBar_2 2522
-#define wxXmlResource_LoadMenuBar_1 2523
-#define wxXmlResource_LoadPanel_2 2524
-#define wxXmlResource_LoadPanel_3 2525
-#define wxXmlResource_LoadToolBar 2526
-#define wxXmlResource_Set 2527
-#define wxXmlResource_SetFlags 2528
-#define wxXmlResource_Unload 2529
-#define wxXmlResource_xrcctrl 2530
-#define wxHtmlEasyPrinting_new 2531
-#define wxHtmlEasyPrinting_destruct 2532
-#define wxHtmlEasyPrinting_GetPrintData 2533
-#define wxHtmlEasyPrinting_GetPageSetupData 2534
-#define wxHtmlEasyPrinting_PreviewFile 2535
-#define wxHtmlEasyPrinting_PreviewText 2536
-#define wxHtmlEasyPrinting_PrintFile 2537
-#define wxHtmlEasyPrinting_PrintText 2538
-#define wxHtmlEasyPrinting_PageSetup 2539
-#define wxHtmlEasyPrinting_SetFonts 2540
-#define wxHtmlEasyPrinting_SetHeader 2541
-#define wxHtmlEasyPrinting_SetFooter 2542
-#define wxGLCanvas_new_2 2544
-#define wxGLCanvas_new_3_1 2545
-#define wxGLCanvas_new_3_0 2546
-#define wxGLCanvas_GetContext 2547
-#define wxGLCanvas_SetCurrent 2549
-#define wxGLCanvas_SwapBuffers 2550
-#define wxGLCanvas_destroy 2551
-#define wxAuiManager_new 2552
-#define wxAuiManager_destruct 2553
-#define wxAuiManager_AddPane_2_1 2554
-#define wxAuiManager_AddPane_3 2555
-#define wxAuiManager_AddPane_2_0 2556
-#define wxAuiManager_DetachPane 2557
-#define wxAuiManager_GetAllPanes 2558
-#define wxAuiManager_GetArtProvider 2559
-#define wxAuiManager_GetDockSizeConstraint 2560
-#define wxAuiManager_GetFlags 2561
-#define wxAuiManager_GetManagedWindow 2562
-#define wxAuiManager_GetManager 2563
-#define wxAuiManager_GetPane_1_1 2564
-#define wxAuiManager_GetPane_1_0 2565
-#define wxAuiManager_HideHint 2566
-#define wxAuiManager_InsertPane 2567
-#define wxAuiManager_LoadPaneInfo 2568
-#define wxAuiManager_LoadPerspective 2569
-#define wxAuiManager_SavePaneInfo 2570
-#define wxAuiManager_SavePerspective 2571
-#define wxAuiManager_SetArtProvider 2572
-#define wxAuiManager_SetDockSizeConstraint 2573
-#define wxAuiManager_SetFlags 2574
-#define wxAuiManager_SetManagedWindow 2575
-#define wxAuiManager_ShowHint 2576
-#define wxAuiManager_UnInit 2577
-#define wxAuiManager_Update 2578
-#define wxAuiPaneInfo_new_0 2579
-#define wxAuiPaneInfo_new_1 2580
-#define wxAuiPaneInfo_destruct 2581
-#define wxAuiPaneInfo_BestSize_1 2582
-#define wxAuiPaneInfo_BestSize_2 2583
-#define wxAuiPaneInfo_Bottom 2584
-#define wxAuiPaneInfo_BottomDockable 2585
-#define wxAuiPaneInfo_Caption 2586
-#define wxAuiPaneInfo_CaptionVisible 2587
-#define wxAuiPaneInfo_Centre 2588
-#define wxAuiPaneInfo_CentrePane 2589
-#define wxAuiPaneInfo_CloseButton 2590
-#define wxAuiPaneInfo_DefaultPane 2591
-#define wxAuiPaneInfo_DestroyOnClose 2592
-#define wxAuiPaneInfo_Direction 2593
-#define wxAuiPaneInfo_Dock 2594
-#define wxAuiPaneInfo_Dockable 2595
-#define wxAuiPaneInfo_Fixed 2596
-#define wxAuiPaneInfo_Float 2597
-#define wxAuiPaneInfo_Floatable 2598
-#define wxAuiPaneInfo_FloatingPosition_1 2599
-#define wxAuiPaneInfo_FloatingPosition_2 2600
-#define wxAuiPaneInfo_FloatingSize_1 2601
-#define wxAuiPaneInfo_FloatingSize_2 2602
-#define wxAuiPaneInfo_Gripper 2603
-#define wxAuiPaneInfo_GripperTop 2604
-#define wxAuiPaneInfo_HasBorder 2605
-#define wxAuiPaneInfo_HasCaption 2606
-#define wxAuiPaneInfo_HasCloseButton 2607
-#define wxAuiPaneInfo_HasFlag 2608
-#define wxAuiPaneInfo_HasGripper 2609
-#define wxAuiPaneInfo_HasGripperTop 2610
-#define wxAuiPaneInfo_HasMaximizeButton 2611
-#define wxAuiPaneInfo_HasMinimizeButton 2612
-#define wxAuiPaneInfo_HasPinButton 2613
-#define wxAuiPaneInfo_Hide 2614
-#define wxAuiPaneInfo_IsBottomDockable 2615
-#define wxAuiPaneInfo_IsDocked 2616
-#define wxAuiPaneInfo_IsFixed 2617
-#define wxAuiPaneInfo_IsFloatable 2618
-#define wxAuiPaneInfo_IsFloating 2619
-#define wxAuiPaneInfo_IsLeftDockable 2620
-#define wxAuiPaneInfo_IsMovable 2621
-#define wxAuiPaneInfo_IsOk 2622
-#define wxAuiPaneInfo_IsResizable 2623
-#define wxAuiPaneInfo_IsRightDockable 2624
-#define wxAuiPaneInfo_IsShown 2625
-#define wxAuiPaneInfo_IsToolbar 2626
-#define wxAuiPaneInfo_IsTopDockable 2627
-#define wxAuiPaneInfo_Layer 2628
-#define wxAuiPaneInfo_Left 2629
-#define wxAuiPaneInfo_LeftDockable 2630
-#define wxAuiPaneInfo_MaxSize_1 2631
-#define wxAuiPaneInfo_MaxSize_2 2632
-#define wxAuiPaneInfo_MaximizeButton 2633
-#define wxAuiPaneInfo_MinSize_1 2634
-#define wxAuiPaneInfo_MinSize_2 2635
-#define wxAuiPaneInfo_MinimizeButton 2636
-#define wxAuiPaneInfo_Movable 2637
-#define wxAuiPaneInfo_Name 2638
-#define wxAuiPaneInfo_PaneBorder 2639
-#define wxAuiPaneInfo_PinButton 2640
-#define wxAuiPaneInfo_Position 2641
-#define wxAuiPaneInfo_Resizable 2642
-#define wxAuiPaneInfo_Right 2643
-#define wxAuiPaneInfo_RightDockable 2644
-#define wxAuiPaneInfo_Row 2645
-#define wxAuiPaneInfo_SafeSet 2646
-#define wxAuiPaneInfo_SetFlag 2647
-#define wxAuiPaneInfo_Show 2648
-#define wxAuiPaneInfo_ToolbarPane 2649
-#define wxAuiPaneInfo_Top 2650
-#define wxAuiPaneInfo_TopDockable 2651
-#define wxAuiPaneInfo_Window 2652
-#define wxAuiPaneInfo_GetWindow 2653
-#define wxAuiPaneInfo_GetFrame 2654
-#define wxAuiPaneInfo_GetDirection 2655
-#define wxAuiPaneInfo_GetLayer 2656
-#define wxAuiPaneInfo_GetRow 2657
-#define wxAuiPaneInfo_GetPosition 2658
-#define wxAuiPaneInfo_GetFloatingPosition 2659
-#define wxAuiPaneInfo_GetFloatingSize 2660
-#define wxAuiNotebook_new_0 2661
-#define wxAuiNotebook_new_2 2662
-#define wxAuiNotebook_AddPage 2663
-#define wxAuiNotebook_Create 2664
-#define wxAuiNotebook_DeletePage 2665
-#define wxAuiNotebook_GetArtProvider 2666
-#define wxAuiNotebook_GetPage 2667
-#define wxAuiNotebook_GetPageBitmap 2668
-#define wxAuiNotebook_GetPageCount 2669
-#define wxAuiNotebook_GetPageIndex 2670
-#define wxAuiNotebook_GetPageText 2671
-#define wxAuiNotebook_GetSelection 2672
-#define wxAuiNotebook_InsertPage 2673
-#define wxAuiNotebook_RemovePage 2674
-#define wxAuiNotebook_SetArtProvider 2675
-#define wxAuiNotebook_SetFont 2676
-#define wxAuiNotebook_SetPageBitmap 2677
-#define wxAuiNotebook_SetPageText 2678
-#define wxAuiNotebook_SetSelection 2679
-#define wxAuiNotebook_SetTabCtrlHeight 2680
-#define wxAuiNotebook_SetUniformBitmapSize 2681
-#define wxAuiNotebook_destroy 2682
-#define wxAuiTabArt_SetFlags 2683
-#define wxAuiTabArt_SetMeasuringFont 2684
-#define wxAuiTabArt_SetNormalFont 2685
-#define wxAuiTabArt_SetSelectedFont 2686
-#define wxAuiTabArt_SetColour 2687
-#define wxAuiTabArt_SetActiveColour 2688
-#define wxAuiDockArt_GetColour 2689
-#define wxAuiDockArt_GetFont 2690
-#define wxAuiDockArt_GetMetric 2691
-#define wxAuiDockArt_SetColour 2692
-#define wxAuiDockArt_SetFont 2693
-#define wxAuiDockArt_SetMetric 2694
-#define wxAuiSimpleTabArt_new 2695
-#define wxAuiSimpleTabArt_destroy 2696
-#define wxMDIParentFrame_new_0 2697
-#define wxMDIParentFrame_new_4 2698
-#define wxMDIParentFrame_destruct 2699
-#define wxMDIParentFrame_ActivateNext 2700
-#define wxMDIParentFrame_ActivatePrevious 2701
-#define wxMDIParentFrame_ArrangeIcons 2702
-#define wxMDIParentFrame_Cascade 2703
-#define wxMDIParentFrame_Create 2704
-#define wxMDIParentFrame_GetActiveChild 2705
-#define wxMDIParentFrame_GetClientWindow 2706
-#define wxMDIParentFrame_Tile 2707
-#define wxMDIChildFrame_new_0 2708
-#define wxMDIChildFrame_new_4 2709
-#define wxMDIChildFrame_destruct 2710
-#define wxMDIChildFrame_Activate 2711
-#define wxMDIChildFrame_Create 2712
-#define wxMDIChildFrame_Maximize 2713
-#define wxMDIChildFrame_Restore 2714
-#define wxMDIClientWindow_new_0 2715
-#define wxMDIClientWindow_new_2 2716
-#define wxMDIClientWindow_destruct 2717
-#define wxMDIClientWindow_CreateClient 2718
-#define wxLayoutAlgorithm_new 2719
-#define wxLayoutAlgorithm_LayoutFrame 2720
-#define wxLayoutAlgorithm_LayoutMDIFrame 2721
-#define wxLayoutAlgorithm_LayoutWindow 2722
-#define wxLayoutAlgorithm_destroy 2723
-#define wxEvent_GetId 2724
-#define wxEvent_GetSkipped 2725
-#define wxEvent_GetTimestamp 2726
-#define wxEvent_IsCommandEvent 2727
-#define wxEvent_ResumePropagation 2728
-#define wxEvent_ShouldPropagate 2729
-#define wxEvent_Skip 2730
-#define wxEvent_StopPropagation 2731
-#define wxCommandEvent_getClientData 2732
-#define wxCommandEvent_GetExtraLong 2733
-#define wxCommandEvent_GetInt 2734
-#define wxCommandEvent_GetSelection 2735
-#define wxCommandEvent_GetString 2736
-#define wxCommandEvent_IsChecked 2737
-#define wxCommandEvent_IsSelection 2738
-#define wxCommandEvent_SetInt 2739
-#define wxCommandEvent_SetString 2740
-#define wxScrollEvent_GetOrientation 2741
-#define wxScrollEvent_GetPosition 2742
-#define wxScrollWinEvent_GetOrientation 2743
-#define wxScrollWinEvent_GetPosition 2744
-#define wxMouseEvent_AltDown 2745
-#define wxMouseEvent_Button 2746
-#define wxMouseEvent_ButtonDClick 2747
-#define wxMouseEvent_ButtonDown 2748
-#define wxMouseEvent_ButtonUp 2749
-#define wxMouseEvent_CmdDown 2750
-#define wxMouseEvent_ControlDown 2751
-#define wxMouseEvent_Dragging 2752
-#define wxMouseEvent_Entering 2753
-#define wxMouseEvent_GetButton 2754
-#define wxMouseEvent_GetPosition 2757
-#define wxMouseEvent_GetLogicalPosition 2758
-#define wxMouseEvent_GetLinesPerAction 2759
-#define wxMouseEvent_GetWheelRotation 2760
-#define wxMouseEvent_GetWheelDelta 2761
-#define wxMouseEvent_GetX 2762
-#define wxMouseEvent_GetY 2763
-#define wxMouseEvent_IsButton 2764
-#define wxMouseEvent_IsPageScroll 2765
-#define wxMouseEvent_Leaving 2766
-#define wxMouseEvent_LeftDClick 2767
-#define wxMouseEvent_LeftDown 2768
-#define wxMouseEvent_LeftIsDown 2769
-#define wxMouseEvent_LeftUp 2770
-#define wxMouseEvent_MetaDown 2771
-#define wxMouseEvent_MiddleDClick 2772
-#define wxMouseEvent_MiddleDown 2773
-#define wxMouseEvent_MiddleIsDown 2774
-#define wxMouseEvent_MiddleUp 2775
-#define wxMouseEvent_Moving 2776
-#define wxMouseEvent_RightDClick 2777
-#define wxMouseEvent_RightDown 2778
-#define wxMouseEvent_RightIsDown 2779
-#define wxMouseEvent_RightUp 2780
-#define wxMouseEvent_ShiftDown 2781
-#define wxSetCursorEvent_GetCursor 2782
-#define wxSetCursorEvent_GetX 2783
-#define wxSetCursorEvent_GetY 2784
-#define wxSetCursorEvent_HasCursor 2785
-#define wxSetCursorEvent_SetCursor 2786
-#define wxKeyEvent_AltDown 2787
-#define wxKeyEvent_CmdDown 2788
-#define wxKeyEvent_ControlDown 2789
-#define wxKeyEvent_GetKeyCode 2790
-#define wxKeyEvent_GetModifiers 2791
-#define wxKeyEvent_GetPosition 2794
-#define wxKeyEvent_GetRawKeyCode 2795
-#define wxKeyEvent_GetRawKeyFlags 2796
-#define wxKeyEvent_GetUnicodeKey 2797
-#define wxKeyEvent_GetX 2798
-#define wxKeyEvent_GetY 2799
-#define wxKeyEvent_HasModifiers 2800
-#define wxKeyEvent_MetaDown 2801
-#define wxKeyEvent_ShiftDown 2802
-#define wxSizeEvent_GetSize 2803
-#define wxMoveEvent_GetPosition 2804
-#define wxEraseEvent_GetDC 2805
-#define wxFocusEvent_GetWindow 2806
-#define wxChildFocusEvent_GetWindow 2807
-#define wxMenuEvent_GetMenu 2808
-#define wxMenuEvent_GetMenuId 2809
-#define wxMenuEvent_IsPopup 2810
-#define wxCloseEvent_CanVeto 2811
-#define wxCloseEvent_GetLoggingOff 2812
-#define wxCloseEvent_SetCanVeto 2813
-#define wxCloseEvent_SetLoggingOff 2814
-#define wxCloseEvent_Veto 2815
-#define wxShowEvent_SetShow 2816
-#define wxShowEvent_GetShow 2817
-#define wxIconizeEvent_Iconized 2818
-#define wxJoystickEvent_ButtonDown 2819
-#define wxJoystickEvent_ButtonIsDown 2820
-#define wxJoystickEvent_ButtonUp 2821
-#define wxJoystickEvent_GetButtonChange 2822
-#define wxJoystickEvent_GetButtonState 2823
-#define wxJoystickEvent_GetJoystick 2824
-#define wxJoystickEvent_GetPosition 2825
-#define wxJoystickEvent_GetZPosition 2826
-#define wxJoystickEvent_IsButton 2827
-#define wxJoystickEvent_IsMove 2828
-#define wxJoystickEvent_IsZMove 2829
-#define wxUpdateUIEvent_CanUpdate 2830
-#define wxUpdateUIEvent_Check 2831
-#define wxUpdateUIEvent_Enable 2832
-#define wxUpdateUIEvent_Show 2833
-#define wxUpdateUIEvent_GetChecked 2834
-#define wxUpdateUIEvent_GetEnabled 2835
-#define wxUpdateUIEvent_GetShown 2836
-#define wxUpdateUIEvent_GetSetChecked 2837
-#define wxUpdateUIEvent_GetSetEnabled 2838
-#define wxUpdateUIEvent_GetSetShown 2839
-#define wxUpdateUIEvent_GetSetText 2840
-#define wxUpdateUIEvent_GetText 2841
-#define wxUpdateUIEvent_GetMode 2842
-#define wxUpdateUIEvent_GetUpdateInterval 2843
-#define wxUpdateUIEvent_ResetUpdateTime 2844
-#define wxUpdateUIEvent_SetMode 2845
-#define wxUpdateUIEvent_SetText 2846
-#define wxUpdateUIEvent_SetUpdateInterval 2847
-#define wxMouseCaptureChangedEvent_GetCapturedWindow 2848
-#define wxPaletteChangedEvent_SetChangedWindow 2849
-#define wxPaletteChangedEvent_GetChangedWindow 2850
-#define wxQueryNewPaletteEvent_SetPaletteRealized 2851
-#define wxQueryNewPaletteEvent_GetPaletteRealized 2852
-#define wxNavigationKeyEvent_GetDirection 2853
-#define wxNavigationKeyEvent_SetDirection 2854
-#define wxNavigationKeyEvent_IsWindowChange 2855
-#define wxNavigationKeyEvent_SetWindowChange 2856
-#define wxNavigationKeyEvent_IsFromTab 2857
-#define wxNavigationKeyEvent_SetFromTab 2858
-#define wxNavigationKeyEvent_GetCurrentFocus 2859
-#define wxNavigationKeyEvent_SetCurrentFocus 2860
-#define wxHelpEvent_GetOrigin 2861
-#define wxHelpEvent_GetPosition 2862
-#define wxHelpEvent_SetOrigin 2863
-#define wxHelpEvent_SetPosition 2864
-#define wxContextMenuEvent_GetPosition 2865
-#define wxContextMenuEvent_SetPosition 2866
-#define wxIdleEvent_CanSend 2867
-#define wxIdleEvent_GetMode 2868
-#define wxIdleEvent_RequestMore 2869
-#define wxIdleEvent_MoreRequested 2870
-#define wxIdleEvent_SetMode 2871
-#define wxGridEvent_AltDown 2872
-#define wxGridEvent_ControlDown 2873
-#define wxGridEvent_GetCol 2874
-#define wxGridEvent_GetPosition 2875
-#define wxGridEvent_GetRow 2876
-#define wxGridEvent_MetaDown 2877
-#define wxGridEvent_Selecting 2878
-#define wxGridEvent_ShiftDown 2879
-#define wxNotifyEvent_Allow 2880
-#define wxNotifyEvent_IsAllowed 2881
-#define wxNotifyEvent_Veto 2882
-#define wxSashEvent_GetEdge 2883
-#define wxSashEvent_GetDragRect 2884
-#define wxSashEvent_GetDragStatus 2885
-#define wxListEvent_GetCacheFrom 2886
-#define wxListEvent_GetCacheTo 2887
-#define wxListEvent_GetKeyCode 2888
-#define wxListEvent_GetIndex 2889
-#define wxListEvent_GetColumn 2890
-#define wxListEvent_GetPoint 2891
-#define wxListEvent_GetLabel 2892
-#define wxListEvent_GetText 2893
-#define wxListEvent_GetImage 2894
-#define wxListEvent_GetData 2895
-#define wxListEvent_GetMask 2896
-#define wxListEvent_GetItem 2897
-#define wxListEvent_IsEditCancelled 2898
-#define wxDateEvent_GetDate 2899
-#define wxCalendarEvent_GetWeekDay 2900
-#define wxFileDirPickerEvent_GetPath 2901
-#define wxColourPickerEvent_GetColour 2902
-#define wxFontPickerEvent_GetFont 2903
-#define wxStyledTextEvent_GetPosition 2904
-#define wxStyledTextEvent_GetKey 2905
-#define wxStyledTextEvent_GetModifiers 2906
-#define wxStyledTextEvent_GetModificationType 2907
-#define wxStyledTextEvent_GetText 2908
-#define wxStyledTextEvent_GetLength 2909
-#define wxStyledTextEvent_GetLinesAdded 2910
-#define wxStyledTextEvent_GetLine 2911
-#define wxStyledTextEvent_GetFoldLevelNow 2912
-#define wxStyledTextEvent_GetFoldLevelPrev 2913
-#define wxStyledTextEvent_GetMargin 2914
-#define wxStyledTextEvent_GetMessage 2915
-#define wxStyledTextEvent_GetWParam 2916
-#define wxStyledTextEvent_GetLParam 2917
-#define wxStyledTextEvent_GetListType 2918
-#define wxStyledTextEvent_GetX 2919
-#define wxStyledTextEvent_GetY 2920
-#define wxStyledTextEvent_GetDragText 2921
-#define wxStyledTextEvent_GetDragAllowMove 2922
-#define wxStyledTextEvent_GetDragResult 2923
-#define wxStyledTextEvent_GetShift 2924
-#define wxStyledTextEvent_GetControl 2925
-#define wxStyledTextEvent_GetAlt 2926
-#define utils_wxGetKeyState 2927
-#define utils_wxGetMousePosition 2928
-#define utils_wxGetMouseState 2929
-#define utils_wxSetDetectableAutoRepeat 2930
-#define utils_wxBell 2931
-#define utils_wxFindMenuItemId 2932
-#define utils_wxGenericFindWindowAtPoint 2933
-#define utils_wxFindWindowAtPoint 2934
-#define utils_wxBeginBusyCursor 2935
-#define utils_wxEndBusyCursor 2936
-#define utils_wxIsBusy 2937
-#define utils_wxShutdown 2938
-#define utils_wxShell 2939
-#define utils_wxLaunchDefaultBrowser 2940
-#define utils_wxGetEmailAddress 2941
-#define utils_wxGetUserId 2942
-#define utils_wxGetHomeDir 2943
-#define utils_wxNewId 2944
-#define utils_wxRegisterId 2945
-#define utils_wxGetCurrentId 2946
-#define utils_wxGetOsDescription 2947
-#define utils_wxIsPlatformLittleEndian 2948
-#define utils_wxIsPlatform64Bit 2949
-#define gdicmn_wxDisplaySize 2950
-#define gdicmn_wxSetCursor 2951
-#define wxPrintout_new 2952
-#define wxPrintout_destruct 2953
-#define wxPrintout_GetDC 2954
-#define wxPrintout_GetPageSizeMM 2955
-#define wxPrintout_GetPageSizePixels 2956
-#define wxPrintout_GetPaperRectPixels 2957
-#define wxPrintout_GetPPIPrinter 2958
-#define wxPrintout_GetPPIScreen 2959
-#define wxPrintout_GetTitle 2960
-#define wxPrintout_IsPreview 2961
-#define wxPrintout_FitThisSizeToPaper 2962
-#define wxPrintout_FitThisSizeToPage 2963
-#define wxPrintout_FitThisSizeToPageMargins 2964
-#define wxPrintout_MapScreenSizeToPaper 2965
-#define wxPrintout_MapScreenSizeToPage 2966
-#define wxPrintout_MapScreenSizeToPageMargins 2967
-#define wxPrintout_MapScreenSizeToDevice 2968
-#define wxPrintout_GetLogicalPaperRect 2969
-#define wxPrintout_GetLogicalPageRect 2970
-#define wxPrintout_GetLogicalPageMarginsRect 2971
-#define wxPrintout_SetLogicalOrigin 2972
-#define wxPrintout_OffsetLogicalOrigin 2973
-#define wxStyledTextCtrl_new_2 2974
-#define wxStyledTextCtrl_new_0 2975
-#define wxStyledTextCtrl_destruct 2976
-#define wxStyledTextCtrl_Create 2977
-#define wxStyledTextCtrl_AddText 2978
-#define wxStyledTextCtrl_AddStyledText 2979
-#define wxStyledTextCtrl_InsertText 2980
-#define wxStyledTextCtrl_ClearAll 2981
-#define wxStyledTextCtrl_ClearDocumentStyle 2982
-#define wxStyledTextCtrl_GetLength 2983
-#define wxStyledTextCtrl_GetCharAt 2984
-#define wxStyledTextCtrl_GetCurrentPos 2985
-#define wxStyledTextCtrl_GetAnchor 2986
-#define wxStyledTextCtrl_GetStyleAt 2987
-#define wxStyledTextCtrl_Redo 2988
-#define wxStyledTextCtrl_SetUndoCollection 2989
-#define wxStyledTextCtrl_SelectAll 2990
-#define wxStyledTextCtrl_SetSavePoint 2991
-#define wxStyledTextCtrl_GetStyledText 2992
-#define wxStyledTextCtrl_CanRedo 2993
-#define wxStyledTextCtrl_MarkerLineFromHandle 2994
-#define wxStyledTextCtrl_MarkerDeleteHandle 2995
-#define wxStyledTextCtrl_GetUndoCollection 2996
-#define wxStyledTextCtrl_GetViewWhiteSpace 2997
-#define wxStyledTextCtrl_SetViewWhiteSpace 2998
-#define wxStyledTextCtrl_PositionFromPoint 2999
-#define wxStyledTextCtrl_PositionFromPointClose 3000
-#define wxStyledTextCtrl_GotoLine 3001
-#define wxStyledTextCtrl_GotoPos 3002
-#define wxStyledTextCtrl_SetAnchor 3003
-#define wxStyledTextCtrl_GetCurLine 3004
-#define wxStyledTextCtrl_GetEndStyled 3005
-#define wxStyledTextCtrl_ConvertEOLs 3006
-#define wxStyledTextCtrl_GetEOLMode 3007
-#define wxStyledTextCtrl_SetEOLMode 3008
-#define wxStyledTextCtrl_StartStyling 3009
-#define wxStyledTextCtrl_SetStyling 3010
-#define wxStyledTextCtrl_GetBufferedDraw 3011
-#define wxStyledTextCtrl_SetBufferedDraw 3012
-#define wxStyledTextCtrl_SetTabWidth 3013
-#define wxStyledTextCtrl_GetTabWidth 3014
-#define wxStyledTextCtrl_SetCodePage 3015
-#define wxStyledTextCtrl_MarkerDefine 3016
-#define wxStyledTextCtrl_MarkerSetForeground 3017
-#define wxStyledTextCtrl_MarkerSetBackground 3018
-#define wxStyledTextCtrl_MarkerAdd 3019
-#define wxStyledTextCtrl_MarkerDelete 3020
-#define wxStyledTextCtrl_MarkerDeleteAll 3021
-#define wxStyledTextCtrl_MarkerGet 3022
-#define wxStyledTextCtrl_MarkerNext 3023
-#define wxStyledTextCtrl_MarkerPrevious 3024
-#define wxStyledTextCtrl_MarkerDefineBitmap 3025
-#define wxStyledTextCtrl_MarkerAddSet 3026
-#define wxStyledTextCtrl_MarkerSetAlpha 3027
-#define wxStyledTextCtrl_SetMarginType 3028
-#define wxStyledTextCtrl_GetMarginType 3029
-#define wxStyledTextCtrl_SetMarginWidth 3030
-#define wxStyledTextCtrl_GetMarginWidth 3031
-#define wxStyledTextCtrl_SetMarginMask 3032
-#define wxStyledTextCtrl_GetMarginMask 3033
-#define wxStyledTextCtrl_SetMarginSensitive 3034
-#define wxStyledTextCtrl_GetMarginSensitive 3035
-#define wxStyledTextCtrl_StyleClearAll 3036
-#define wxStyledTextCtrl_StyleSetForeground 3037
-#define wxStyledTextCtrl_StyleSetBackground 3038
-#define wxStyledTextCtrl_StyleSetBold 3039
-#define wxStyledTextCtrl_StyleSetItalic 3040
-#define wxStyledTextCtrl_StyleSetSize 3041
-#define wxStyledTextCtrl_StyleSetFaceName 3042
-#define wxStyledTextCtrl_StyleSetEOLFilled 3043
-#define wxStyledTextCtrl_StyleResetDefault 3044
-#define wxStyledTextCtrl_StyleSetUnderline 3045
-#define wxStyledTextCtrl_StyleSetCase 3046
-#define wxStyledTextCtrl_StyleSetHotSpot 3047
-#define wxStyledTextCtrl_SetSelForeground 3048
-#define wxStyledTextCtrl_SetSelBackground 3049
-#define wxStyledTextCtrl_GetSelAlpha 3050
-#define wxStyledTextCtrl_SetSelAlpha 3051
-#define wxStyledTextCtrl_SetCaretForeground 3052
-#define wxStyledTextCtrl_CmdKeyAssign 3053
-#define wxStyledTextCtrl_CmdKeyClear 3054
-#define wxStyledTextCtrl_CmdKeyClearAll 3055
-#define wxStyledTextCtrl_SetStyleBytes 3056
-#define wxStyledTextCtrl_StyleSetVisible 3057
-#define wxStyledTextCtrl_GetCaretPeriod 3058
-#define wxStyledTextCtrl_SetCaretPeriod 3059
-#define wxStyledTextCtrl_SetWordChars 3060
-#define wxStyledTextCtrl_BeginUndoAction 3061
-#define wxStyledTextCtrl_EndUndoAction 3062
-#define wxStyledTextCtrl_IndicatorSetStyle 3063
-#define wxStyledTextCtrl_IndicatorGetStyle 3064
-#define wxStyledTextCtrl_IndicatorSetForeground 3065
-#define wxStyledTextCtrl_IndicatorGetForeground 3066
-#define wxStyledTextCtrl_SetWhitespaceForeground 3067
-#define wxStyledTextCtrl_SetWhitespaceBackground 3068
-#define wxStyledTextCtrl_GetStyleBits 3069
-#define wxStyledTextCtrl_SetLineState 3070
-#define wxStyledTextCtrl_GetLineState 3071
-#define wxStyledTextCtrl_GetMaxLineState 3072
-#define wxStyledTextCtrl_GetCaretLineVisible 3073
-#define wxStyledTextCtrl_SetCaretLineVisible 3074
-#define wxStyledTextCtrl_GetCaretLineBackground 3075
-#define wxStyledTextCtrl_SetCaretLineBackground 3076
-#define wxStyledTextCtrl_AutoCompShow 3077
-#define wxStyledTextCtrl_AutoCompCancel 3078
-#define wxStyledTextCtrl_AutoCompActive 3079
-#define wxStyledTextCtrl_AutoCompPosStart 3080
-#define wxStyledTextCtrl_AutoCompComplete 3081
-#define wxStyledTextCtrl_AutoCompStops 3082
-#define wxStyledTextCtrl_AutoCompSetSeparator 3083
-#define wxStyledTextCtrl_AutoCompGetSeparator 3084
-#define wxStyledTextCtrl_AutoCompSelect 3085
-#define wxStyledTextCtrl_AutoCompSetCancelAtStart 3086
-#define wxStyledTextCtrl_AutoCompGetCancelAtStart 3087
-#define wxStyledTextCtrl_AutoCompSetFillUps 3088
-#define wxStyledTextCtrl_AutoCompSetChooseSingle 3089
-#define wxStyledTextCtrl_AutoCompGetChooseSingle 3090
-#define wxStyledTextCtrl_AutoCompSetIgnoreCase 3091
-#define wxStyledTextCtrl_AutoCompGetIgnoreCase 3092
-#define wxStyledTextCtrl_UserListShow 3093
-#define wxStyledTextCtrl_AutoCompSetAutoHide 3094
-#define wxStyledTextCtrl_AutoCompGetAutoHide 3095
-#define wxStyledTextCtrl_AutoCompSetDropRestOfWord 3096
-#define wxStyledTextCtrl_AutoCompGetDropRestOfWord 3097
-#define wxStyledTextCtrl_RegisterImage 3098
-#define wxStyledTextCtrl_ClearRegisteredImages 3099
-#define wxStyledTextCtrl_AutoCompGetTypeSeparator 3100
-#define wxStyledTextCtrl_AutoCompSetTypeSeparator 3101
-#define wxStyledTextCtrl_AutoCompSetMaxWidth 3102
-#define wxStyledTextCtrl_AutoCompGetMaxWidth 3103
-#define wxStyledTextCtrl_AutoCompSetMaxHeight 3104
-#define wxStyledTextCtrl_AutoCompGetMaxHeight 3105
-#define wxStyledTextCtrl_SetIndent 3106
-#define wxStyledTextCtrl_GetIndent 3107
-#define wxStyledTextCtrl_SetUseTabs 3108
-#define wxStyledTextCtrl_GetUseTabs 3109
-#define wxStyledTextCtrl_SetLineIndentation 3110
-#define wxStyledTextCtrl_GetLineIndentation 3111
-#define wxStyledTextCtrl_GetLineIndentPosition 3112
-#define wxStyledTextCtrl_GetColumn 3113
-#define wxStyledTextCtrl_SetUseHorizontalScrollBar 3114
-#define wxStyledTextCtrl_GetUseHorizontalScrollBar 3115
-#define wxStyledTextCtrl_SetIndentationGuides 3116
-#define wxStyledTextCtrl_GetIndentationGuides 3117
-#define wxStyledTextCtrl_SetHighlightGuide 3118
-#define wxStyledTextCtrl_GetHighlightGuide 3119
-#define wxStyledTextCtrl_GetLineEndPosition 3120
-#define wxStyledTextCtrl_GetCodePage 3121
-#define wxStyledTextCtrl_GetCaretForeground 3122
-#define wxStyledTextCtrl_GetReadOnly 3123
-#define wxStyledTextCtrl_SetCurrentPos 3124
-#define wxStyledTextCtrl_SetSelectionStart 3125
-#define wxStyledTextCtrl_GetSelectionStart 3126
-#define wxStyledTextCtrl_SetSelectionEnd 3127
-#define wxStyledTextCtrl_GetSelectionEnd 3128
-#define wxStyledTextCtrl_SetPrintMagnification 3129
-#define wxStyledTextCtrl_GetPrintMagnification 3130
-#define wxStyledTextCtrl_SetPrintColourMode 3131
-#define wxStyledTextCtrl_GetPrintColourMode 3132
-#define wxStyledTextCtrl_FindText 3133
-#define wxStyledTextCtrl_FormatRange 3134
-#define wxStyledTextCtrl_GetFirstVisibleLine 3135
-#define wxStyledTextCtrl_GetLine 3136
-#define wxStyledTextCtrl_GetLineCount 3137
-#define wxStyledTextCtrl_SetMarginLeft 3138
-#define wxStyledTextCtrl_GetMarginLeft 3139
-#define wxStyledTextCtrl_SetMarginRight 3140
-#define wxStyledTextCtrl_GetMarginRight 3141
-#define wxStyledTextCtrl_GetModify 3142
-#define wxStyledTextCtrl_SetSelection 3143
-#define wxStyledTextCtrl_GetSelectedText 3144
-#define wxStyledTextCtrl_GetTextRange 3145
-#define wxStyledTextCtrl_HideSelection 3146
-#define wxStyledTextCtrl_LineFromPosition 3147
-#define wxStyledTextCtrl_PositionFromLine 3148
-#define wxStyledTextCtrl_LineScroll 3149
-#define wxStyledTextCtrl_EnsureCaretVisible 3150
-#define wxStyledTextCtrl_ReplaceSelection 3151
-#define wxStyledTextCtrl_SetReadOnly 3152
-#define wxStyledTextCtrl_CanPaste 3153
-#define wxStyledTextCtrl_CanUndo 3154
-#define wxStyledTextCtrl_EmptyUndoBuffer 3155
-#define wxStyledTextCtrl_Undo 3156
-#define wxStyledTextCtrl_Cut 3157
-#define wxStyledTextCtrl_Copy 3158
-#define wxStyledTextCtrl_Paste 3159
-#define wxStyledTextCtrl_Clear 3160
-#define wxStyledTextCtrl_SetText 3161
-#define wxStyledTextCtrl_GetText 3162
-#define wxStyledTextCtrl_GetTextLength 3163
-#define wxStyledTextCtrl_GetOvertype 3164
-#define wxStyledTextCtrl_SetCaretWidth 3165
-#define wxStyledTextCtrl_GetCaretWidth 3166
-#define wxStyledTextCtrl_SetTargetStart 3167
-#define wxStyledTextCtrl_GetTargetStart 3168
-#define wxStyledTextCtrl_SetTargetEnd 3169
-#define wxStyledTextCtrl_GetTargetEnd 3170
-#define wxStyledTextCtrl_ReplaceTarget 3171
-#define wxStyledTextCtrl_SearchInTarget 3172
-#define wxStyledTextCtrl_SetSearchFlags 3173
-#define wxStyledTextCtrl_GetSearchFlags 3174
-#define wxStyledTextCtrl_CallTipShow 3175
-#define wxStyledTextCtrl_CallTipCancel 3176
-#define wxStyledTextCtrl_CallTipActive 3177
-#define wxStyledTextCtrl_CallTipPosAtStart 3178
-#define wxStyledTextCtrl_CallTipSetHighlight 3179
-#define wxStyledTextCtrl_CallTipSetBackground 3180
-#define wxStyledTextCtrl_CallTipSetForeground 3181
-#define wxStyledTextCtrl_CallTipSetForegroundHighlight 3182
-#define wxStyledTextCtrl_CallTipUseStyle 3183
-#define wxStyledTextCtrl_VisibleFromDocLine 3184
-#define wxStyledTextCtrl_DocLineFromVisible 3185
-#define wxStyledTextCtrl_WrapCount 3186
-#define wxStyledTextCtrl_SetFoldLevel 3187
-#define wxStyledTextCtrl_GetFoldLevel 3188
-#define wxStyledTextCtrl_GetLastChild 3189
-#define wxStyledTextCtrl_GetFoldParent 3190
-#define wxStyledTextCtrl_ShowLines 3191
-#define wxStyledTextCtrl_HideLines 3192
-#define wxStyledTextCtrl_GetLineVisible 3193
-#define wxStyledTextCtrl_SetFoldExpanded 3194
-#define wxStyledTextCtrl_GetFoldExpanded 3195
-#define wxStyledTextCtrl_ToggleFold 3196
-#define wxStyledTextCtrl_EnsureVisible 3197
-#define wxStyledTextCtrl_SetFoldFlags 3198
-#define wxStyledTextCtrl_EnsureVisibleEnforcePolicy 3199
-#define wxStyledTextCtrl_SetTabIndents 3200
-#define wxStyledTextCtrl_GetTabIndents 3201
-#define wxStyledTextCtrl_SetBackSpaceUnIndents 3202
-#define wxStyledTextCtrl_GetBackSpaceUnIndents 3203
-#define wxStyledTextCtrl_SetMouseDwellTime 3204
-#define wxStyledTextCtrl_GetMouseDwellTime 3205
-#define wxStyledTextCtrl_WordStartPosition 3206
-#define wxStyledTextCtrl_WordEndPosition 3207
-#define wxStyledTextCtrl_SetWrapMode 3208
-#define wxStyledTextCtrl_GetWrapMode 3209
-#define wxStyledTextCtrl_SetWrapVisualFlags 3210
-#define wxStyledTextCtrl_GetWrapVisualFlags 3211
-#define wxStyledTextCtrl_SetWrapVisualFlagsLocation 3212
-#define wxStyledTextCtrl_GetWrapVisualFlagsLocation 3213
-#define wxStyledTextCtrl_SetWrapStartIndent 3214
-#define wxStyledTextCtrl_GetWrapStartIndent 3215
-#define wxStyledTextCtrl_SetLayoutCache 3216
-#define wxStyledTextCtrl_GetLayoutCache 3217
-#define wxStyledTextCtrl_SetScrollWidth 3218
-#define wxStyledTextCtrl_GetScrollWidth 3219
-#define wxStyledTextCtrl_TextWidth 3220
-#define wxStyledTextCtrl_GetEndAtLastLine 3221
-#define wxStyledTextCtrl_TextHeight 3222
-#define wxStyledTextCtrl_SetUseVerticalScrollBar 3223
-#define wxStyledTextCtrl_GetUseVerticalScrollBar 3224
-#define wxStyledTextCtrl_AppendText 3225
-#define wxStyledTextCtrl_GetTwoPhaseDraw 3226
-#define wxStyledTextCtrl_SetTwoPhaseDraw 3227
-#define wxStyledTextCtrl_TargetFromSelection 3228
-#define wxStyledTextCtrl_LinesJoin 3229
-#define wxStyledTextCtrl_LinesSplit 3230
-#define wxStyledTextCtrl_SetFoldMarginColour 3231
-#define wxStyledTextCtrl_SetFoldMarginHiColour 3232
-#define wxStyledTextCtrl_LineDown 3233
-#define wxStyledTextCtrl_LineDownExtend 3234
-#define wxStyledTextCtrl_LineUp 3235
-#define wxStyledTextCtrl_LineUpExtend 3236
-#define wxStyledTextCtrl_CharLeft 3237
-#define wxStyledTextCtrl_CharLeftExtend 3238
-#define wxStyledTextCtrl_CharRight 3239
-#define wxStyledTextCtrl_CharRightExtend 3240
-#define wxStyledTextCtrl_WordLeft 3241
-#define wxStyledTextCtrl_WordLeftExtend 3242
-#define wxStyledTextCtrl_WordRight 3243
-#define wxStyledTextCtrl_WordRightExtend 3244
-#define wxStyledTextCtrl_Home 3245
-#define wxStyledTextCtrl_HomeExtend 3246
-#define wxStyledTextCtrl_LineEnd 3247
-#define wxStyledTextCtrl_LineEndExtend 3248
-#define wxStyledTextCtrl_DocumentStart 3249
-#define wxStyledTextCtrl_DocumentStartExtend 3250
-#define wxStyledTextCtrl_DocumentEnd 3251
-#define wxStyledTextCtrl_DocumentEndExtend 3252
-#define wxStyledTextCtrl_PageUp 3253
-#define wxStyledTextCtrl_PageUpExtend 3254
-#define wxStyledTextCtrl_PageDown 3255
-#define wxStyledTextCtrl_PageDownExtend 3256
-#define wxStyledTextCtrl_EditToggleOvertype 3257
-#define wxStyledTextCtrl_Cancel 3258
-#define wxStyledTextCtrl_DeleteBack 3259
-#define wxStyledTextCtrl_Tab 3260
-#define wxStyledTextCtrl_BackTab 3261
-#define wxStyledTextCtrl_NewLine 3262
-#define wxStyledTextCtrl_FormFeed 3263
-#define wxStyledTextCtrl_VCHome 3264
-#define wxStyledTextCtrl_VCHomeExtend 3265
-#define wxStyledTextCtrl_ZoomIn 3266
-#define wxStyledTextCtrl_ZoomOut 3267
-#define wxStyledTextCtrl_DelWordLeft 3268
-#define wxStyledTextCtrl_DelWordRight 3269
-#define wxStyledTextCtrl_LineCut 3270
-#define wxStyledTextCtrl_LineDelete 3271
-#define wxStyledTextCtrl_LineTranspose 3272
-#define wxStyledTextCtrl_LineDuplicate 3273
-#define wxStyledTextCtrl_LowerCase 3274
-#define wxStyledTextCtrl_UpperCase 3275
-#define wxStyledTextCtrl_LineScrollDown 3276
-#define wxStyledTextCtrl_LineScrollUp 3277
-#define wxStyledTextCtrl_DeleteBackNotLine 3278
-#define wxStyledTextCtrl_HomeDisplay 3279
-#define wxStyledTextCtrl_HomeDisplayExtend 3280
-#define wxStyledTextCtrl_LineEndDisplay 3281
-#define wxStyledTextCtrl_LineEndDisplayExtend 3282
-#define wxStyledTextCtrl_HomeWrapExtend 3283
-#define wxStyledTextCtrl_LineEndWrap 3284
-#define wxStyledTextCtrl_LineEndWrapExtend 3285
-#define wxStyledTextCtrl_VCHomeWrap 3286
-#define wxStyledTextCtrl_VCHomeWrapExtend 3287
-#define wxStyledTextCtrl_LineCopy 3288
-#define wxStyledTextCtrl_MoveCaretInsideView 3289
-#define wxStyledTextCtrl_LineLength 3290
-#define wxStyledTextCtrl_BraceHighlight 3291
-#define wxStyledTextCtrl_BraceBadLight 3292
-#define wxStyledTextCtrl_BraceMatch 3293
-#define wxStyledTextCtrl_GetViewEOL 3294
-#define wxStyledTextCtrl_SetViewEOL 3295
-#define wxStyledTextCtrl_SetModEventMask 3296
-#define wxStyledTextCtrl_GetEdgeColumn 3297
-#define wxStyledTextCtrl_SetEdgeColumn 3298
-#define wxStyledTextCtrl_SetEdgeMode 3299
-#define wxStyledTextCtrl_GetEdgeMode 3300
-#define wxStyledTextCtrl_GetEdgeColour 3301
-#define wxStyledTextCtrl_SetEdgeColour 3302
-#define wxStyledTextCtrl_SearchAnchor 3303
-#define wxStyledTextCtrl_SearchNext 3304
-#define wxStyledTextCtrl_SearchPrev 3305
-#define wxStyledTextCtrl_LinesOnScreen 3306
-#define wxStyledTextCtrl_UsePopUp 3307
-#define wxStyledTextCtrl_SelectionIsRectangle 3308
-#define wxStyledTextCtrl_SetZoom 3309
-#define wxStyledTextCtrl_GetZoom 3310
-#define wxStyledTextCtrl_GetModEventMask 3311
-#define wxStyledTextCtrl_SetSTCFocus 3312
-#define wxStyledTextCtrl_GetSTCFocus 3313
-#define wxStyledTextCtrl_SetStatus 3314
-#define wxStyledTextCtrl_GetStatus 3315
-#define wxStyledTextCtrl_SetMouseDownCaptures 3316
-#define wxStyledTextCtrl_GetMouseDownCaptures 3317
-#define wxStyledTextCtrl_SetSTCCursor 3318
-#define wxStyledTextCtrl_GetSTCCursor 3319
-#define wxStyledTextCtrl_SetControlCharSymbol 3320
-#define wxStyledTextCtrl_GetControlCharSymbol 3321
-#define wxStyledTextCtrl_WordPartLeft 3322
-#define wxStyledTextCtrl_WordPartLeftExtend 3323
-#define wxStyledTextCtrl_WordPartRight 3324
-#define wxStyledTextCtrl_WordPartRightExtend 3325
-#define wxStyledTextCtrl_SetVisiblePolicy 3326
-#define wxStyledTextCtrl_DelLineLeft 3327
-#define wxStyledTextCtrl_DelLineRight 3328
-#define wxStyledTextCtrl_GetXOffset 3329
-#define wxStyledTextCtrl_ChooseCaretX 3330
-#define wxStyledTextCtrl_SetXCaretPolicy 3331
-#define wxStyledTextCtrl_SetYCaretPolicy 3332
-#define wxStyledTextCtrl_GetPrintWrapMode 3333
-#define wxStyledTextCtrl_SetHotspotActiveForeground 3334
-#define wxStyledTextCtrl_SetHotspotActiveBackground 3335
-#define wxStyledTextCtrl_SetHotspotActiveUnderline 3336
-#define wxStyledTextCtrl_SetHotspotSingleLine 3337
-#define wxStyledTextCtrl_ParaDownExtend 3338
-#define wxStyledTextCtrl_ParaUp 3339
-#define wxStyledTextCtrl_ParaUpExtend 3340
-#define wxStyledTextCtrl_PositionBefore 3341
-#define wxStyledTextCtrl_PositionAfter 3342
-#define wxStyledTextCtrl_CopyRange 3343
-#define wxStyledTextCtrl_CopyText 3344
-#define wxStyledTextCtrl_SetSelectionMode 3345
-#define wxStyledTextCtrl_GetSelectionMode 3346
-#define wxStyledTextCtrl_LineDownRectExtend 3347
-#define wxStyledTextCtrl_LineUpRectExtend 3348
-#define wxStyledTextCtrl_CharLeftRectExtend 3349
-#define wxStyledTextCtrl_CharRightRectExtend 3350
-#define wxStyledTextCtrl_HomeRectExtend 3351
-#define wxStyledTextCtrl_VCHomeRectExtend 3352
-#define wxStyledTextCtrl_LineEndRectExtend 3353
-#define wxStyledTextCtrl_PageUpRectExtend 3354
-#define wxStyledTextCtrl_PageDownRectExtend 3355
-#define wxStyledTextCtrl_StutteredPageUp 3356
-#define wxStyledTextCtrl_StutteredPageUpExtend 3357
-#define wxStyledTextCtrl_StutteredPageDown 3358
-#define wxStyledTextCtrl_StutteredPageDownExtend 3359
-#define wxStyledTextCtrl_WordLeftEnd 3360
-#define wxStyledTextCtrl_WordLeftEndExtend 3361
-#define wxStyledTextCtrl_WordRightEnd 3362
-#define wxStyledTextCtrl_WordRightEndExtend 3363
-#define wxStyledTextCtrl_SetWhitespaceChars 3364
-#define wxStyledTextCtrl_SetCharsDefault 3365
-#define wxStyledTextCtrl_AutoCompGetCurrent 3366
-#define wxStyledTextCtrl_Allocate 3367
-#define wxStyledTextCtrl_FindColumn 3368
-#define wxStyledTextCtrl_GetCaretSticky 3369
-#define wxStyledTextCtrl_SetCaretSticky 3370
-#define wxStyledTextCtrl_ToggleCaretSticky 3371
-#define wxStyledTextCtrl_SetPasteConvertEndings 3372
-#define wxStyledTextCtrl_GetPasteConvertEndings 3373
-#define wxStyledTextCtrl_SelectionDuplicate 3374
-#define wxStyledTextCtrl_SetCaretLineBackAlpha 3375
-#define wxStyledTextCtrl_GetCaretLineBackAlpha 3376
-#define wxStyledTextCtrl_StartRecord 3377
-#define wxStyledTextCtrl_StopRecord 3378
-#define wxStyledTextCtrl_SetLexer 3379
-#define wxStyledTextCtrl_GetLexer 3380
-#define wxStyledTextCtrl_Colourise 3381
-#define wxStyledTextCtrl_SetProperty 3382
-#define wxStyledTextCtrl_SetKeyWords 3383
-#define wxStyledTextCtrl_SetLexerLanguage 3384
-#define wxStyledTextCtrl_GetProperty 3385
-#define wxStyledTextCtrl_GetStyleBitsNeeded 3386
-#define wxStyledTextCtrl_GetCurrentLine 3387
-#define wxStyledTextCtrl_StyleSetSpec 3388
-#define wxStyledTextCtrl_StyleSetFont 3389
-#define wxStyledTextCtrl_StyleSetFontAttr 3390
-#define wxStyledTextCtrl_StyleSetCharacterSet 3391
-#define wxStyledTextCtrl_StyleSetFontEncoding 3392
-#define wxStyledTextCtrl_CmdKeyExecute 3393
-#define wxStyledTextCtrl_SetMargins 3394
-#define wxStyledTextCtrl_GetSelection 3395
-#define wxStyledTextCtrl_PointFromPosition 3396
-#define wxStyledTextCtrl_ScrollToLine 3397
-#define wxStyledTextCtrl_ScrollToColumn 3398
-#define wxStyledTextCtrl_SetVScrollBar 3399
-#define wxStyledTextCtrl_SetHScrollBar 3400
-#define wxStyledTextCtrl_GetLastKeydownProcessed 3401
-#define wxStyledTextCtrl_SetLastKeydownProcessed 3402
-#define wxStyledTextCtrl_SaveFile 3403
-#define wxStyledTextCtrl_LoadFile 3404
-#define wxStyledTextCtrl_DoDragOver 3405
-#define wxStyledTextCtrl_DoDropText 3406
-#define wxStyledTextCtrl_GetUseAntiAliasing 3407
-#define wxStyledTextCtrl_AddTextRaw 3408
-#define wxStyledTextCtrl_InsertTextRaw 3409
-#define wxStyledTextCtrl_GetCurLineRaw 3410
-#define wxStyledTextCtrl_GetLineRaw 3411
-#define wxStyledTextCtrl_GetSelectedTextRaw 3412
-#define wxStyledTextCtrl_GetTextRangeRaw 3413
-#define wxStyledTextCtrl_SetTextRaw 3414
-#define wxStyledTextCtrl_GetTextRaw 3415
-#define wxStyledTextCtrl_AppendTextRaw 3416
-#define wxArtProvider_GetBitmap 3417
-#define wxArtProvider_GetIcon 3418
-#define wxTreeEvent_GetKeyCode 3419
-#define wxTreeEvent_GetItem 3420
-#define wxTreeEvent_GetKeyEvent 3421
-#define wxTreeEvent_GetLabel 3422
-#define wxTreeEvent_GetOldItem 3423
-#define wxTreeEvent_GetPoint 3424
-#define wxTreeEvent_IsEditCancelled 3425
-#define wxTreeEvent_SetToolTip 3426
-#define wxNotebookEvent_GetOldSelection 3427
-#define wxNotebookEvent_GetSelection 3428
-#define wxNotebookEvent_SetOldSelection 3429
-#define wxNotebookEvent_SetSelection 3430
-#define wxFileDataObject_new 3431
-#define wxFileDataObject_AddFile 3432
-#define wxFileDataObject_GetFilenames 3433
-#define wxFileDataObject_destroy 3434
-#define wxTextDataObject_new 3435
-#define wxTextDataObject_GetTextLength 3436
-#define wxTextDataObject_GetText 3437
-#define wxTextDataObject_SetText 3438
-#define wxTextDataObject_destroy 3439
-#define wxBitmapDataObject_new_1_1 3440
-#define wxBitmapDataObject_new_1_0 3441
-#define wxBitmapDataObject_GetBitmap 3442
-#define wxBitmapDataObject_SetBitmap 3443
-#define wxBitmapDataObject_destroy 3444
-#define wxClipboard_new 3446
-#define wxClipboard_destruct 3447
-#define wxClipboard_AddData 3448
-#define wxClipboard_Clear 3449
-#define wxClipboard_Close 3450
-#define wxClipboard_Flush 3451
-#define wxClipboard_GetData 3452
-#define wxClipboard_IsOpened 3453
-#define wxClipboard_Open 3454
-#define wxClipboard_SetData 3455
-#define wxClipboard_UsePrimarySelection 3457
-#define wxClipboard_IsSupported 3458
-#define wxClipboard_Get 3459
-#define wxSpinEvent_GetPosition 3460
-#define wxSpinEvent_SetPosition 3461
-#define wxSplitterWindow_new_0 3462
-#define wxSplitterWindow_new_2 3463
-#define wxSplitterWindow_destruct 3464
-#define wxSplitterWindow_Create 3465
-#define wxSplitterWindow_GetMinimumPaneSize 3466
-#define wxSplitterWindow_GetSashGravity 3467
-#define wxSplitterWindow_GetSashPosition 3468
-#define wxSplitterWindow_GetSplitMode 3469
-#define wxSplitterWindow_GetWindow1 3470
-#define wxSplitterWindow_GetWindow2 3471
-#define wxSplitterWindow_Initialize 3472
-#define wxSplitterWindow_IsSplit 3473
-#define wxSplitterWindow_ReplaceWindow 3474
-#define wxSplitterWindow_SetSashGravity 3475
-#define wxSplitterWindow_SetSashPosition 3476
-#define wxSplitterWindow_SetSashSize 3477
-#define wxSplitterWindow_SetMinimumPaneSize 3478
-#define wxSplitterWindow_SetSplitMode 3479
-#define wxSplitterWindow_SplitHorizontally 3480
-#define wxSplitterWindow_SplitVertically 3481
-#define wxSplitterWindow_Unsplit 3482
-#define wxSplitterWindow_UpdateSize 3483
-#define wxSplitterEvent_GetSashPosition 3484
-#define wxSplitterEvent_GetX 3485
-#define wxSplitterEvent_GetY 3486
-#define wxSplitterEvent_GetWindowBeingRemoved 3487
-#define wxSplitterEvent_SetSashPosition 3488
-#define wxHtmlWindow_new_0 3489
-#define wxHtmlWindow_new_2 3490
-#define wxHtmlWindow_AppendToPage 3491
-#define wxHtmlWindow_GetOpenedAnchor 3492
-#define wxHtmlWindow_GetOpenedPage 3493
-#define wxHtmlWindow_GetOpenedPageTitle 3494
-#define wxHtmlWindow_GetRelatedFrame 3495
-#define wxHtmlWindow_HistoryBack 3496
-#define wxHtmlWindow_HistoryCanBack 3497
-#define wxHtmlWindow_HistoryCanForward 3498
-#define wxHtmlWindow_HistoryClear 3499
-#define wxHtmlWindow_HistoryForward 3500
-#define wxHtmlWindow_LoadFile 3501
-#define wxHtmlWindow_LoadPage 3502
-#define wxHtmlWindow_SelectAll 3503
-#define wxHtmlWindow_SelectionToText 3504
-#define wxHtmlWindow_SelectLine 3505
-#define wxHtmlWindow_SelectWord 3506
-#define wxHtmlWindow_SetBorders 3507
-#define wxHtmlWindow_SetFonts 3508
-#define wxHtmlWindow_SetPage 3509
-#define wxHtmlWindow_SetRelatedFrame 3510
-#define wxHtmlWindow_SetRelatedStatusBar 3511
-#define wxHtmlWindow_ToText 3512
-#define wxHtmlWindow_destroy 3513
-#define wxHtmlLinkEvent_GetLinkInfo 3514
-#define wxSystemSettings_GetColour 3515
-#define wxSystemSettings_GetFont 3516
-#define wxSystemSettings_GetMetric 3517
-#define wxSystemSettings_GetScreenType 3518
-#define wxSystemOptions_GetOption 3519
-#define wxSystemOptions_GetOptionInt 3520
-#define wxSystemOptions_HasOption 3521
-#define wxSystemOptions_IsFalse 3522
-#define wxSystemOptions_SetOption_2_1 3523
-#define wxSystemOptions_SetOption_2_0 3524
-#define wxAuiNotebookEvent_SetSelection 3525
-#define wxAuiNotebookEvent_GetSelection 3526
-#define wxAuiNotebookEvent_SetOldSelection 3527
-#define wxAuiNotebookEvent_GetOldSelection 3528
-#define wxAuiNotebookEvent_SetDragSource 3529
-#define wxAuiNotebookEvent_GetDragSource 3530
-#define wxAuiManagerEvent_SetManager 3531
-#define wxAuiManagerEvent_GetManager 3532
-#define wxAuiManagerEvent_SetPane 3533
-#define wxAuiManagerEvent_GetPane 3534
-#define wxAuiManagerEvent_SetButton 3535
-#define wxAuiManagerEvent_GetButton 3536
-#define wxAuiManagerEvent_SetDC 3537
-#define wxAuiManagerEvent_GetDC 3538
-#define wxAuiManagerEvent_Veto 3539
-#define wxAuiManagerEvent_GetVeto 3540
-#define wxAuiManagerEvent_SetCanVeto 3541
-#define wxAuiManagerEvent_CanVeto 3542
-#define wxLogNull_new 3543
-#define wxLogNull_destroy 3544
-#define wxTaskBarIcon_new 3545
-#define wxTaskBarIcon_destruct 3546
-#define wxTaskBarIcon_PopupMenu 3547
-#define wxTaskBarIcon_RemoveIcon 3548
-#define wxTaskBarIcon_SetIcon 3549
-#define wxLocale_new_0 3550
-#define wxLocale_new_2 3552
-#define wxLocale_destruct 3553
-#define wxLocale_Init 3555
-#define wxLocale_AddCatalog_1 3556
-#define wxLocale_AddCatalog_3 3557
-#define wxLocale_AddCatalogLookupPathPrefix 3558
-#define wxLocale_GetCanonicalName 3559
-#define wxLocale_GetLanguage 3560
-#define wxLocale_GetLanguageName 3561
-#define wxLocale_GetLocale 3562
-#define wxLocale_GetName 3563
-#define wxLocale_GetString_2 3564
-#define wxLocale_GetString_4 3565
-#define wxLocale_GetHeaderValue 3566
-#define wxLocale_GetSysName 3567
-#define wxLocale_GetSystemEncoding 3568
-#define wxLocale_GetSystemEncodingName 3569
-#define wxLocale_GetSystemLanguage 3570
-#define wxLocale_IsLoaded 3571
-#define wxLocale_IsOk 3572
-#define wxActivateEvent_GetActive 3573
-#define wxPopupWindow_new_2 3575
-#define wxPopupWindow_new_0 3576
-#define wxPopupWindow_destruct 3578
-#define wxPopupWindow_Create 3579
-#define wxPopupWindow_Position 3580
-#define wxPopupTransientWindow_new_0 3581
-#define wxPopupTransientWindow_new_2 3582
-#define wxPopupTransientWindow_destruct 3583
-#define wxPopupTransientWindow_Popup 3584
-#define wxPopupTransientWindow_Dismiss 3585
+#define wxToolBar_AddStretchableSpace 984
+#define wxToolBar_InsertStretchableSpace 985
+#define wxToolBar_DeleteTool 986
+#define wxToolBar_DeleteToolByPos 987
+#define wxToolBar_EnableTool 988
+#define wxToolBar_FindById 989
+#define wxToolBar_FindControl 990
+#define wxToolBar_FindToolForPosition 991
+#define wxToolBar_GetToolSize 992
+#define wxToolBar_GetToolBitmapSize 993
+#define wxToolBar_GetMargins 994
+#define wxToolBar_GetToolEnabled 995
+#define wxToolBar_GetToolLongHelp 996
+#define wxToolBar_GetToolPacking 997
+#define wxToolBar_GetToolPos 998
+#define wxToolBar_GetToolSeparation 999
+#define wxToolBar_GetToolShortHelp 1000
+#define wxToolBar_GetToolState 1001
+#define wxToolBar_InsertControl 1002
+#define wxToolBar_InsertSeparator 1003
+#define wxToolBar_InsertTool_5 1004
+#define wxToolBar_InsertTool_2 1005
+#define wxToolBar_InsertTool_4 1006
+#define wxToolBar_Realize 1007
+#define wxToolBar_RemoveTool 1008
+#define wxToolBar_SetMargins 1009
+#define wxToolBar_SetToolBitmapSize 1010
+#define wxToolBar_SetToolLongHelp 1011
+#define wxToolBar_SetToolPacking 1012
+#define wxToolBar_SetToolShortHelp 1013
+#define wxToolBar_SetToolSeparation 1014
+#define wxToolBar_ToggleTool 1015
+#define wxStatusBar_new_0 1017
+#define wxStatusBar_new_2 1018
+#define wxStatusBar_destruct 1020
+#define wxStatusBar_Create 1021
+#define wxStatusBar_GetFieldRect 1022
+#define wxStatusBar_GetFieldsCount 1023
+#define wxStatusBar_GetStatusText 1024
+#define wxStatusBar_PopStatusText 1025
+#define wxStatusBar_PushStatusText 1026
+#define wxStatusBar_SetFieldsCount 1027
+#define wxStatusBar_SetMinHeight 1028
+#define wxStatusBar_SetStatusText 1029
+#define wxStatusBar_SetStatusWidths 1030
+#define wxStatusBar_SetStatusStyles 1031
+#define wxBitmap_new_0 1032
+#define wxBitmap_new_3 1033
+#define wxBitmap_new_4 1034
+#define wxBitmap_new_2_0 1035
+#define wxBitmap_new_2_1 1036
+#define wxBitmap_destruct 1037
+#define wxBitmap_ConvertToImage 1038
+#define wxBitmap_CopyFromIcon 1039
+#define wxBitmap_Create 1040
+#define wxBitmap_GetDepth 1041
+#define wxBitmap_GetHeight 1042
+#define wxBitmap_GetPalette 1043
+#define wxBitmap_GetMask 1044
+#define wxBitmap_GetWidth 1045
+#define wxBitmap_GetSubBitmap 1046
+#define wxBitmap_LoadFile 1047
+#define wxBitmap_Ok 1048
+#define wxBitmap_SaveFile 1049
+#define wxBitmap_SetDepth 1050
+#define wxBitmap_SetHeight 1051
+#define wxBitmap_SetMask 1052
+#define wxBitmap_SetPalette 1053
+#define wxBitmap_SetWidth 1054
+#define wxIcon_new_0 1055
+#define wxIcon_new_2 1056
+#define wxIcon_new_1 1057
+#define wxIcon_CopyFromBitmap 1058
+#define wxIcon_destroy 1059
+#define wxIconBundle_new_0 1060
+#define wxIconBundle_new_2 1061
+#define wxIconBundle_new_1_0 1062
+#define wxIconBundle_new_1_1 1063
+#define wxIconBundle_destruct 1064
+#define wxIconBundle_AddIcon_2 1065
+#define wxIconBundle_AddIcon_1 1066
+#define wxIconBundle_GetIcon_1_1 1067
+#define wxIconBundle_GetIcon_1_0 1068
+#define wxCursor_new_0 1069
+#define wxCursor_new_1_0 1070
+#define wxCursor_new_1_1 1071
+#define wxCursor_new_4 1072
+#define wxCursor_destruct 1073
+#define wxCursor_Ok 1074
+#define wxMask_new_0 1075
+#define wxMask_new_2_1 1076
+#define wxMask_new_2_0 1077
+#define wxMask_new_1 1078
+#define wxMask_destruct 1079
+#define wxMask_Create_2_1 1080
+#define wxMask_Create_2_0 1081
+#define wxMask_Create_1 1082
+#define wxImage_new_0 1083
+#define wxImage_new_3_0 1084
+#define wxImage_new_4 1085
+#define wxImage_new_5 1086
+#define wxImage_new_2 1087
+#define wxImage_new_3_1 1088
+#define wxImage_Blur 1089
+#define wxImage_BlurHorizontal 1090
+#define wxImage_BlurVertical 1091
+#define wxImage_ConvertAlphaToMask 1092
+#define wxImage_ConvertToGreyscale 1093
+#define wxImage_ConvertToMono 1094
+#define wxImage_Copy 1095
+#define wxImage_Create_3 1096
+#define wxImage_Create_4 1097
+#define wxImage_Create_5 1098
+#define wxImage_Destroy 1099
+#define wxImage_FindFirstUnusedColour 1100
+#define wxImage_GetImageExtWildcard 1101
+#define wxImage_GetAlpha_2 1102
+#define wxImage_GetAlpha_0 1103
+#define wxImage_GetBlue 1104
+#define wxImage_GetData 1105
+#define wxImage_GetGreen 1106
+#define wxImage_GetImageCount 1107
+#define wxImage_GetHeight 1108
+#define wxImage_GetMaskBlue 1109
+#define wxImage_GetMaskGreen 1110
+#define wxImage_GetMaskRed 1111
+#define wxImage_GetOrFindMaskColour 1112
+#define wxImage_GetPalette 1113
+#define wxImage_GetRed 1114
+#define wxImage_GetSubImage 1115
+#define wxImage_GetWidth 1116
+#define wxImage_HasAlpha 1117
+#define wxImage_HasMask 1118
+#define wxImage_GetOption 1119
+#define wxImage_GetOptionInt 1120
+#define wxImage_HasOption 1121
+#define wxImage_InitAlpha 1122
+#define wxImage_InitStandardHandlers 1123
+#define wxImage_IsTransparent 1124
+#define wxImage_LoadFile_2 1125
+#define wxImage_LoadFile_3 1126
+#define wxImage_Ok 1127
+#define wxImage_RemoveHandler 1128
+#define wxImage_Mirror 1129
+#define wxImage_Replace 1130
+#define wxImage_Rescale 1131
+#define wxImage_Resize 1132
+#define wxImage_Rotate 1133
+#define wxImage_RotateHue 1134
+#define wxImage_Rotate90 1135
+#define wxImage_SaveFile_1 1136
+#define wxImage_SaveFile_2_0 1137
+#define wxImage_SaveFile_2_1 1138
+#define wxImage_Scale 1139
+#define wxImage_Size 1140
+#define wxImage_SetAlpha_3 1141
+#define wxImage_SetAlpha_2 1142
+#define wxImage_SetData_2 1143
+#define wxImage_SetData_4 1144
+#define wxImage_SetMask 1145
+#define wxImage_SetMaskColour 1146
+#define wxImage_SetMaskFromImage 1147
+#define wxImage_SetOption_2_1 1148
+#define wxImage_SetOption_2_0 1149
+#define wxImage_SetPalette 1150
+#define wxImage_SetRGB_5 1151
+#define wxImage_SetRGB_4 1152
+#define wxImage_destroy 1153
+#define wxBrush_new_0 1154
+#define wxBrush_new_2 1155
+#define wxBrush_new_1 1156
+#define wxBrush_destruct 1158
+#define wxBrush_GetColour 1159
+#define wxBrush_GetStipple 1160
+#define wxBrush_GetStyle 1161
+#define wxBrush_IsHatch 1162
+#define wxBrush_IsOk 1163
+#define wxBrush_SetColour_1 1164
+#define wxBrush_SetColour_3 1165
+#define wxBrush_SetStipple 1166
+#define wxBrush_SetStyle 1167
+#define wxPen_new_0 1168
+#define wxPen_new_2 1169
+#define wxPen_destruct 1170
+#define wxPen_GetCap 1171
+#define wxPen_GetColour 1172
+#define wxPen_GetJoin 1173
+#define wxPen_GetStyle 1174
+#define wxPen_GetWidth 1175
+#define wxPen_IsOk 1176
+#define wxPen_SetCap 1177
+#define wxPen_SetColour_1 1178
+#define wxPen_SetColour_3 1179
+#define wxPen_SetJoin 1180
+#define wxPen_SetStyle 1181
+#define wxPen_SetWidth 1182
+#define wxRegion_new_0 1183
+#define wxRegion_new_4 1184
+#define wxRegion_new_2 1185
+#define wxRegion_new_1_1 1186
+#define wxRegion_new_1_0 1188
+#define wxRegion_destruct 1190
+#define wxRegion_Clear 1191
+#define wxRegion_Contains_2 1192
+#define wxRegion_Contains_1_0 1193
+#define wxRegion_Contains_4 1194
+#define wxRegion_Contains_1_1 1195
+#define wxRegion_ConvertToBitmap 1196
+#define wxRegion_GetBox 1197
+#define wxRegion_Intersect_4 1198
+#define wxRegion_Intersect_1_1 1199
+#define wxRegion_Intersect_1_0 1200
+#define wxRegion_IsEmpty 1201
+#define wxRegion_Subtract_4 1202
+#define wxRegion_Subtract_1_1 1203
+#define wxRegion_Subtract_1_0 1204
+#define wxRegion_Offset_2 1205
+#define wxRegion_Offset_1 1206
+#define wxRegion_Union_4 1207
+#define wxRegion_Union_1_2 1208
+#define wxRegion_Union_1_1 1209
+#define wxRegion_Union_1_0 1210
+#define wxRegion_Union_3 1211
+#define wxRegion_Xor_4 1212
+#define wxRegion_Xor_1_1 1213
+#define wxRegion_Xor_1_0 1214
+#define wxAcceleratorTable_new_0 1215
+#define wxAcceleratorTable_new_2 1216
+#define wxAcceleratorTable_destruct 1217
+#define wxAcceleratorTable_Ok 1218
+#define wxAcceleratorEntry_new_1_0 1219
+#define wxAcceleratorEntry_new_1_1 1220
+#define wxAcceleratorEntry_GetCommand 1221
+#define wxAcceleratorEntry_GetFlags 1222
+#define wxAcceleratorEntry_GetKeyCode 1223
+#define wxAcceleratorEntry_Set 1224
+#define wxAcceleratorEntry_destroy 1225
+#define wxCaret_new_3 1230
+#define wxCaret_new_2 1231
+#define wxCaret_destruct 1233
+#define wxCaret_Create_3 1234
+#define wxCaret_Create_2 1235
+#define wxCaret_GetBlinkTime 1236
+#define wxCaret_GetPosition 1238
+#define wxCaret_GetSize 1240
+#define wxCaret_GetWindow 1241
+#define wxCaret_Hide 1242
+#define wxCaret_IsOk 1243
+#define wxCaret_IsVisible 1244
+#define wxCaret_Move_2 1245
+#define wxCaret_Move_1 1246
+#define wxCaret_SetBlinkTime 1247
+#define wxCaret_SetSize_2 1248
+#define wxCaret_SetSize_1 1249
+#define wxCaret_Show 1250
+#define wxSizer_Add_2_1 1251
+#define wxSizer_Add_2_0 1252
+#define wxSizer_Add_3 1253
+#define wxSizer_Add_2_3 1254
+#define wxSizer_Add_2_2 1255
+#define wxSizer_AddSpacer 1256
+#define wxSizer_AddStretchSpacer 1257
+#define wxSizer_CalcMin 1258
+#define wxSizer_Clear 1259
+#define wxSizer_Detach_1_2 1260
+#define wxSizer_Detach_1_1 1261
+#define wxSizer_Detach_1_0 1262
+#define wxSizer_Fit 1263
+#define wxSizer_FitInside 1264
+#define wxSizer_GetChildren 1265
+#define wxSizer_GetItem_2_1 1266
+#define wxSizer_GetItem_2_0 1267
+#define wxSizer_GetItem_1 1268
+#define wxSizer_GetSize 1269
+#define wxSizer_GetPosition 1270
+#define wxSizer_GetMinSize 1271
+#define wxSizer_Hide_2_0 1272
+#define wxSizer_Hide_2_1 1273
+#define wxSizer_Hide_1 1274
+#define wxSizer_Insert_3_1 1275
+#define wxSizer_Insert_3_0 1276
+#define wxSizer_Insert_4 1277
+#define wxSizer_Insert_3_3 1278
+#define wxSizer_Insert_3_2 1279
+#define wxSizer_Insert_2 1280
+#define wxSizer_InsertSpacer 1281
+#define wxSizer_InsertStretchSpacer 1282
+#define wxSizer_IsShown_1_2 1283
+#define wxSizer_IsShown_1_1 1284
+#define wxSizer_IsShown_1_0 1285
+#define wxSizer_Layout 1286
+#define wxSizer_Prepend_2_1 1287
+#define wxSizer_Prepend_2_0 1288
+#define wxSizer_Prepend_3 1289
+#define wxSizer_Prepend_2_3 1290
+#define wxSizer_Prepend_2_2 1291
+#define wxSizer_Prepend_1 1292
+#define wxSizer_PrependSpacer 1293
+#define wxSizer_PrependStretchSpacer 1294
+#define wxSizer_RecalcSizes 1295
+#define wxSizer_Remove_1_1 1296
+#define wxSizer_Remove_1_0 1297
+#define wxSizer_Replace_3_1 1298
+#define wxSizer_Replace_3_0 1299
+#define wxSizer_Replace_2 1300
+#define wxSizer_SetDimension 1301
+#define wxSizer_SetMinSize_2 1302
+#define wxSizer_SetMinSize_1 1303
+#define wxSizer_SetItemMinSize_3_2 1304
+#define wxSizer_SetItemMinSize_2_2 1305
+#define wxSizer_SetItemMinSize_3_1 1306
+#define wxSizer_SetItemMinSize_2_1 1307
+#define wxSizer_SetItemMinSize_3_0 1308
+#define wxSizer_SetItemMinSize_2_0 1309
+#define wxSizer_SetSizeHints 1310
+#define wxSizer_SetVirtualSizeHints 1311
+#define wxSizer_Show_2_2 1312
+#define wxSizer_Show_2_1 1313
+#define wxSizer_Show_2_0 1314
+#define wxSizer_Show_1 1315
+#define wxSizerFlags_new 1316
+#define wxSizerFlags_Align 1317
+#define wxSizerFlags_Border_2 1318
+#define wxSizerFlags_Border_1 1319
+#define wxSizerFlags_Center 1320
+#define wxSizerFlags_Centre 1321
+#define wxSizerFlags_Expand 1322
+#define wxSizerFlags_Left 1323
+#define wxSizerFlags_Proportion 1324
+#define wxSizerFlags_Right 1325
+#define wxSizerFlags_destroy 1326
+#define wxSizerItem_new_5_1 1327
+#define wxSizerItem_new_2_1 1328
+#define wxSizerItem_new_5_0 1329
+#define wxSizerItem_new_2_0 1330
+#define wxSizerItem_new_6 1331
+#define wxSizerItem_new_3 1332
+#define wxSizerItem_new_0 1333
+#define wxSizerItem_destruct 1334
+#define wxSizerItem_CalcMin 1335
+#define wxSizerItem_DeleteWindows 1336
+#define wxSizerItem_DetachSizer 1337
+#define wxSizerItem_GetBorder 1338
+#define wxSizerItem_GetFlag 1339
+#define wxSizerItem_GetMinSize 1340
+#define wxSizerItem_GetPosition 1341
+#define wxSizerItem_GetProportion 1342
+#define wxSizerItem_GetRatio 1343
+#define wxSizerItem_GetRect 1344
+#define wxSizerItem_GetSize 1345
+#define wxSizerItem_GetSizer 1346
+#define wxSizerItem_GetSpacer 1347
+#define wxSizerItem_GetUserData 1348
+#define wxSizerItem_GetWindow 1349
+#define wxSizerItem_IsSizer 1350
+#define wxSizerItem_IsShown 1351
+#define wxSizerItem_IsSpacer 1352
+#define wxSizerItem_IsWindow 1353
+#define wxSizerItem_SetBorder 1354
+#define wxSizerItem_SetDimension 1355
+#define wxSizerItem_SetFlag 1356
+#define wxSizerItem_SetInitSize 1357
+#define wxSizerItem_SetMinSize_1 1358
+#define wxSizerItem_SetMinSize_2 1359
+#define wxSizerItem_SetProportion 1360
+#define wxSizerItem_SetRatio_2 1361
+#define wxSizerItem_SetRatio_1_1 1362
+#define wxSizerItem_SetRatio_1_0 1363
+#define wxSizerItem_SetSizer 1364
+#define wxSizerItem_SetSpacer_1 1365
+#define wxSizerItem_SetSpacer_2 1366
+#define wxSizerItem_SetWindow 1367
+#define wxSizerItem_Show 1368
+#define wxBoxSizer_new 1369
+#define wxBoxSizer_GetOrientation 1370
+#define wxBoxSizer_destroy 1371
+#define wxStaticBoxSizer_new_2 1372
+#define wxStaticBoxSizer_new_3 1373
+#define wxStaticBoxSizer_GetStaticBox 1374
+#define wxStaticBoxSizer_destroy 1375
+#define wxGridSizer_new_4 1376
+#define wxGridSizer_new_2 1377
+#define wxGridSizer_GetCols 1378
+#define wxGridSizer_GetHGap 1379
+#define wxGridSizer_GetRows 1380
+#define wxGridSizer_GetVGap 1381
+#define wxGridSizer_SetCols 1382
+#define wxGridSizer_SetHGap 1383
+#define wxGridSizer_SetRows 1384
+#define wxGridSizer_SetVGap 1385
+#define wxGridSizer_destroy 1386
+#define wxFlexGridSizer_new_4 1387
+#define wxFlexGridSizer_new_2 1388
+#define wxFlexGridSizer_AddGrowableCol 1389
+#define wxFlexGridSizer_AddGrowableRow 1390
+#define wxFlexGridSizer_GetFlexibleDirection 1391
+#define wxFlexGridSizer_GetNonFlexibleGrowMode 1392
+#define wxFlexGridSizer_RemoveGrowableCol 1393
+#define wxFlexGridSizer_RemoveGrowableRow 1394
+#define wxFlexGridSizer_SetFlexibleDirection 1395
+#define wxFlexGridSizer_SetNonFlexibleGrowMode 1396
+#define wxFlexGridSizer_destroy 1397
+#define wxGridBagSizer_new 1398
+#define wxGridBagSizer_Add_3_2 1399
+#define wxGridBagSizer_Add_3_1 1400
+#define wxGridBagSizer_Add_4 1401
+#define wxGridBagSizer_Add_1_0 1402
+#define wxGridBagSizer_Add_2_1 1403
+#define wxGridBagSizer_Add_2_0 1404
+#define wxGridBagSizer_Add_3_0 1405
+#define wxGridBagSizer_Add_1_1 1406
+#define wxGridBagSizer_CalcMin 1407
+#define wxGridBagSizer_CheckForIntersection_2 1408
+#define wxGridBagSizer_CheckForIntersection_3 1409
+#define wxGridBagSizer_FindItem_1_1 1410
+#define wxGridBagSizer_FindItem_1_0 1411
+#define wxGridBagSizer_FindItemAtPoint 1412
+#define wxGridBagSizer_FindItemAtPosition 1413
+#define wxGridBagSizer_FindItemWithData 1414
+#define wxGridBagSizer_GetCellSize 1415
+#define wxGridBagSizer_GetEmptyCellSize 1416
+#define wxGridBagSizer_GetItemPosition_1_2 1417
+#define wxGridBagSizer_GetItemPosition_1_1 1418
+#define wxGridBagSizer_GetItemPosition_1_0 1419
+#define wxGridBagSizer_GetItemSpan_1_2 1420
+#define wxGridBagSizer_GetItemSpan_1_1 1421
+#define wxGridBagSizer_GetItemSpan_1_0 1422
+#define wxGridBagSizer_SetEmptyCellSize 1423
+#define wxGridBagSizer_SetItemPosition_2_2 1424
+#define wxGridBagSizer_SetItemPosition_2_1 1425
+#define wxGridBagSizer_SetItemPosition_2_0 1426
+#define wxGridBagSizer_SetItemSpan_2_2 1427
+#define wxGridBagSizer_SetItemSpan_2_1 1428
+#define wxGridBagSizer_SetItemSpan_2_0 1429
+#define wxGridBagSizer_destroy 1430
+#define wxStdDialogButtonSizer_new 1431
+#define wxStdDialogButtonSizer_AddButton 1432
+#define wxStdDialogButtonSizer_Realize 1433
+#define wxStdDialogButtonSizer_SetAffirmativeButton 1434
+#define wxStdDialogButtonSizer_SetCancelButton 1435
+#define wxStdDialogButtonSizer_SetNegativeButton 1436
+#define wxStdDialogButtonSizer_destroy 1437
+#define wxFont_new_0 1438
+#define wxFont_new_1 1439
+#define wxFont_new_5 1440
+#define wxFont_destruct 1442
+#define wxFont_IsFixedWidth 1443
+#define wxFont_GetDefaultEncoding 1444
+#define wxFont_GetFaceName 1445
+#define wxFont_GetFamily 1446
+#define wxFont_GetNativeFontInfoDesc 1447
+#define wxFont_GetNativeFontInfoUserDesc 1448
+#define wxFont_GetPointSize 1449
+#define wxFont_GetStyle 1450
+#define wxFont_GetUnderlined 1451
+#define wxFont_GetWeight 1452
+#define wxFont_Ok 1453
+#define wxFont_SetDefaultEncoding 1454
+#define wxFont_SetFaceName 1455
+#define wxFont_SetFamily 1456
+#define wxFont_SetPointSize 1457
+#define wxFont_SetStyle 1458
+#define wxFont_SetUnderlined 1459
+#define wxFont_SetWeight 1460
+#define wxToolTip_Enable 1461
+#define wxToolTip_SetDelay 1462
+#define wxToolTip_new 1463
+#define wxToolTip_SetTip 1464
+#define wxToolTip_GetTip 1465
+#define wxToolTip_GetWindow 1466
+#define wxToolTip_destroy 1467
+#define wxButton_new_3 1469
+#define wxButton_new_0 1470
+#define wxButton_destruct 1471
+#define wxButton_Create 1472
+#define wxButton_GetDefaultSize 1473
+#define wxButton_SetDefault 1474
+#define wxButton_SetLabel 1475
+#define wxBitmapButton_new_4 1477
+#define wxBitmapButton_new_0 1478
+#define wxBitmapButton_Create 1479
+#define wxBitmapButton_GetBitmapDisabled 1480
+#define wxBitmapButton_GetBitmapFocus 1482
+#define wxBitmapButton_GetBitmapLabel 1484
+#define wxBitmapButton_GetBitmapSelected 1486
+#define wxBitmapButton_SetBitmapDisabled 1488
+#define wxBitmapButton_SetBitmapFocus 1489
+#define wxBitmapButton_SetBitmapLabel 1490
+#define wxBitmapButton_SetBitmapSelected 1491
+#define wxBitmapButton_destroy 1492
+#define wxToggleButton_new_0 1493
+#define wxToggleButton_new_4 1494
+#define wxToggleButton_Create 1495
+#define wxToggleButton_GetValue 1496
+#define wxToggleButton_SetValue 1497
+#define wxToggleButton_destroy 1498
+#define wxCalendarCtrl_new_0 1499
+#define wxCalendarCtrl_new_3 1500
+#define wxCalendarCtrl_Create 1501
+#define wxCalendarCtrl_destruct 1502
+#define wxCalendarCtrl_SetDate 1503
+#define wxCalendarCtrl_GetDate 1504
+#define wxCalendarCtrl_EnableYearChange 1505
+#define wxCalendarCtrl_EnableMonthChange 1506
+#define wxCalendarCtrl_EnableHolidayDisplay 1507
+#define wxCalendarCtrl_SetHeaderColours 1508
+#define wxCalendarCtrl_GetHeaderColourFg 1509
+#define wxCalendarCtrl_GetHeaderColourBg 1510
+#define wxCalendarCtrl_SetHighlightColours 1511
+#define wxCalendarCtrl_GetHighlightColourFg 1512
+#define wxCalendarCtrl_GetHighlightColourBg 1513
+#define wxCalendarCtrl_SetHolidayColours 1514
+#define wxCalendarCtrl_GetHolidayColourFg 1515
+#define wxCalendarCtrl_GetHolidayColourBg 1516
+#define wxCalendarCtrl_GetAttr 1517
+#define wxCalendarCtrl_SetAttr 1518
+#define wxCalendarCtrl_SetHoliday 1519
+#define wxCalendarCtrl_ResetAttr 1520
+#define wxCalendarCtrl_HitTest 1521
+#define wxCalendarDateAttr_new_0 1522
+#define wxCalendarDateAttr_new_2_1 1523
+#define wxCalendarDateAttr_new_2_0 1524
+#define wxCalendarDateAttr_SetTextColour 1525
+#define wxCalendarDateAttr_SetBackgroundColour 1526
+#define wxCalendarDateAttr_SetBorderColour 1527
+#define wxCalendarDateAttr_SetFont 1528
+#define wxCalendarDateAttr_SetBorder 1529
+#define wxCalendarDateAttr_SetHoliday 1530
+#define wxCalendarDateAttr_HasTextColour 1531
+#define wxCalendarDateAttr_HasBackgroundColour 1532
+#define wxCalendarDateAttr_HasBorderColour 1533
+#define wxCalendarDateAttr_HasFont 1534
+#define wxCalendarDateAttr_HasBorder 1535
+#define wxCalendarDateAttr_IsHoliday 1536
+#define wxCalendarDateAttr_GetTextColour 1537
+#define wxCalendarDateAttr_GetBackgroundColour 1538
+#define wxCalendarDateAttr_GetBorderColour 1539
+#define wxCalendarDateAttr_GetFont 1540
+#define wxCalendarDateAttr_GetBorder 1541
+#define wxCalendarDateAttr_destroy 1542
+#define wxCheckBox_new_4 1544
+#define wxCheckBox_new_0 1545
+#define wxCheckBox_Create 1546
+#define wxCheckBox_GetValue 1547
+#define wxCheckBox_Get3StateValue 1548
+#define wxCheckBox_Is3rdStateAllowedForUser 1549
+#define wxCheckBox_Is3State 1550
+#define wxCheckBox_IsChecked 1551
+#define wxCheckBox_SetValue 1552
+#define wxCheckBox_Set3StateValue 1553
+#define wxCheckBox_destroy 1554
+#define wxCheckListBox_new_0 1555
+#define wxCheckListBox_new_3 1557
+#define wxCheckListBox_Check 1558
+#define wxCheckListBox_IsChecked 1559
+#define wxCheckListBox_destroy 1560
+#define wxChoice_new_3 1563
+#define wxChoice_new_0 1564
+#define wxChoice_destruct 1566
+#define wxChoice_Create 1568
+#define wxChoice_Delete 1569
+#define wxChoice_GetColumns 1570
+#define wxChoice_SetColumns 1571
+#define wxComboBox_new_0 1572
+#define wxComboBox_new_3 1574
+#define wxComboBox_destruct 1575
+#define wxComboBox_Create 1577
+#define wxComboBox_CanCopy 1578
+#define wxComboBox_CanCut 1579
+#define wxComboBox_CanPaste 1580
+#define wxComboBox_CanRedo 1581
+#define wxComboBox_CanUndo 1582
+#define wxComboBox_Copy 1583
+#define wxComboBox_Cut 1584
+#define wxComboBox_GetInsertionPoint 1585
+#define wxComboBox_GetLastPosition 1586
+#define wxComboBox_GetValue 1587
+#define wxComboBox_Paste 1588
+#define wxComboBox_Redo 1589
+#define wxComboBox_Replace 1590
+#define wxComboBox_Remove 1591
+#define wxComboBox_SetInsertionPoint 1592
+#define wxComboBox_SetInsertionPointEnd 1593
+#define wxComboBox_SetSelection_1 1594
+#define wxComboBox_SetSelection_2 1595
+#define wxComboBox_SetValue 1596
+#define wxComboBox_Undo 1597
+#define wxGauge_new_0 1598
+#define wxGauge_new_4 1599
+#define wxGauge_Create 1600
+#define wxGauge_GetBezelFace 1601
+#define wxGauge_GetRange 1602
+#define wxGauge_GetShadowWidth 1603
+#define wxGauge_GetValue 1604
+#define wxGauge_IsVertical 1605
+#define wxGauge_SetBezelFace 1606
+#define wxGauge_SetRange 1607
+#define wxGauge_SetShadowWidth 1608
+#define wxGauge_SetValue 1609
+#define wxGauge_Pulse 1610
+#define wxGauge_destroy 1611
+#define wxGenericDirCtrl_new_0 1612
+#define wxGenericDirCtrl_new_2 1613
+#define wxGenericDirCtrl_destruct 1614
+#define wxGenericDirCtrl_Create 1615
+#define wxGenericDirCtrl_Init 1616
+#define wxGenericDirCtrl_CollapseTree 1617
+#define wxGenericDirCtrl_ExpandPath 1618
+#define wxGenericDirCtrl_GetDefaultPath 1619
+#define wxGenericDirCtrl_GetPath 1620
+#define wxGenericDirCtrl_GetFilePath 1621
+#define wxGenericDirCtrl_GetFilter 1622
+#define wxGenericDirCtrl_GetFilterIndex 1623
+#define wxGenericDirCtrl_GetRootId 1624
+#define wxGenericDirCtrl_GetTreeCtrl 1625
+#define wxGenericDirCtrl_ReCreateTree 1626
+#define wxGenericDirCtrl_SetDefaultPath 1627
+#define wxGenericDirCtrl_SetFilter 1628
+#define wxGenericDirCtrl_SetFilterIndex 1629
+#define wxGenericDirCtrl_SetPath 1630
+#define wxStaticBox_new_4 1632
+#define wxStaticBox_new_0 1633
+#define wxStaticBox_Create 1634
+#define wxStaticBox_destroy 1635
+#define wxStaticLine_new_2 1637
+#define wxStaticLine_new_0 1638
+#define wxStaticLine_Create 1639
+#define wxStaticLine_IsVertical 1640
+#define wxStaticLine_GetDefaultSize 1641
+#define wxStaticLine_destroy 1642
+#define wxListBox_new_3 1645
+#define wxListBox_new_0 1646
+#define wxListBox_destruct 1648
+#define wxListBox_Create 1650
+#define wxListBox_Deselect 1651
+#define wxListBox_GetSelections 1652
+#define wxListBox_InsertItems 1653
+#define wxListBox_IsSelected 1654
+#define wxListBox_Set 1655
+#define wxListBox_HitTest 1656
+#define wxListBox_SetFirstItem_1_0 1657
+#define wxListBox_SetFirstItem_1_1 1658
+#define wxListCtrl_new_0 1659
+#define wxListCtrl_new_2 1660
+#define wxListCtrl_Arrange 1661
+#define wxListCtrl_AssignImageList 1662
+#define wxListCtrl_ClearAll 1663
+#define wxListCtrl_Create 1664
+#define wxListCtrl_DeleteAllItems 1665
+#define wxListCtrl_DeleteColumn 1666
+#define wxListCtrl_DeleteItem 1667
+#define wxListCtrl_EditLabel 1668
+#define wxListCtrl_EnsureVisible 1669
+#define wxListCtrl_FindItem_3_0 1670
+#define wxListCtrl_FindItem_3_1 1671
+#define wxListCtrl_GetColumn 1672
+#define wxListCtrl_GetColumnCount 1673
+#define wxListCtrl_GetColumnWidth 1674
+#define wxListCtrl_GetCountPerPage 1675
+#define wxListCtrl_GetEditControl 1676
+#define wxListCtrl_GetImageList 1677
+#define wxListCtrl_GetItem 1678
+#define wxListCtrl_GetItemBackgroundColour 1679
+#define wxListCtrl_GetItemCount 1680
+#define wxListCtrl_GetItemData 1681
+#define wxListCtrl_GetItemFont 1682
+#define wxListCtrl_GetItemPosition 1683
+#define wxListCtrl_GetItemRect 1684
+#define wxListCtrl_GetItemSpacing 1685
+#define wxListCtrl_GetItemState 1686
+#define wxListCtrl_GetItemText 1687
+#define wxListCtrl_GetItemTextColour 1688
+#define wxListCtrl_GetNextItem 1689
+#define wxListCtrl_GetSelectedItemCount 1690
+#define wxListCtrl_GetTextColour 1691
+#define wxListCtrl_GetTopItem 1692
+#define wxListCtrl_GetViewRect 1693
+#define wxListCtrl_HitTest 1694
+#define wxListCtrl_InsertColumn_2 1695
+#define wxListCtrl_InsertColumn_3 1696
+#define wxListCtrl_InsertItem_1 1697
+#define wxListCtrl_InsertItem_2_1 1698
+#define wxListCtrl_InsertItem_2_0 1699
+#define wxListCtrl_InsertItem_3 1700
+#define wxListCtrl_RefreshItem 1701
+#define wxListCtrl_RefreshItems 1702
+#define wxListCtrl_ScrollList 1703
+#define wxListCtrl_SetBackgroundColour 1704
+#define wxListCtrl_SetColumn 1705
+#define wxListCtrl_SetColumnWidth 1706
+#define wxListCtrl_SetImageList 1707
+#define wxListCtrl_SetItem_1 1708
+#define wxListCtrl_SetItem_4 1709
+#define wxListCtrl_SetItemBackgroundColour 1710
+#define wxListCtrl_SetItemCount 1711
+#define wxListCtrl_SetItemData 1712
+#define wxListCtrl_SetItemFont 1713
+#define wxListCtrl_SetItemImage 1714
+#define wxListCtrl_SetItemColumnImage 1715
+#define wxListCtrl_SetItemPosition 1716
+#define wxListCtrl_SetItemState 1717
+#define wxListCtrl_SetItemText 1718
+#define wxListCtrl_SetItemTextColour 1719
+#define wxListCtrl_SetSingleStyle 1720
+#define wxListCtrl_SetTextColour 1721
+#define wxListCtrl_SetWindowStyleFlag 1722
+#define wxListCtrl_SortItems 1723
+#define wxListCtrl_destroy 1724
+#define wxListView_ClearColumnImage 1725
+#define wxListView_Focus 1726
+#define wxListView_GetFirstSelected 1727
+#define wxListView_GetFocusedItem 1728
+#define wxListView_GetNextSelected 1729
+#define wxListView_IsSelected 1730
+#define wxListView_Select 1731
+#define wxListView_SetColumnImage 1732
+#define wxListItem_new_0 1733
+#define wxListItem_new_1 1734
+#define wxListItem_destruct 1735
+#define wxListItem_Clear 1736
+#define wxListItem_GetAlign 1737
+#define wxListItem_GetBackgroundColour 1738
+#define wxListItem_GetColumn 1739
+#define wxListItem_GetFont 1740
+#define wxListItem_GetId 1741
+#define wxListItem_GetImage 1742
+#define wxListItem_GetMask 1743
+#define wxListItem_GetState 1744
+#define wxListItem_GetText 1745
+#define wxListItem_GetTextColour 1746
+#define wxListItem_GetWidth 1747
+#define wxListItem_SetAlign 1748
+#define wxListItem_SetBackgroundColour 1749
+#define wxListItem_SetColumn 1750
+#define wxListItem_SetFont 1751
+#define wxListItem_SetId 1752
+#define wxListItem_SetImage 1753
+#define wxListItem_SetMask 1754
+#define wxListItem_SetState 1755
+#define wxListItem_SetStateMask 1756
+#define wxListItem_SetText 1757
+#define wxListItem_SetTextColour 1758
+#define wxListItem_SetWidth 1759
+#define wxListItemAttr_new_0 1760
+#define wxListItemAttr_new_3 1761
+#define wxListItemAttr_GetBackgroundColour 1762
+#define wxListItemAttr_GetFont 1763
+#define wxListItemAttr_GetTextColour 1764
+#define wxListItemAttr_HasBackgroundColour 1765
+#define wxListItemAttr_HasFont 1766
+#define wxListItemAttr_HasTextColour 1767
+#define wxListItemAttr_SetBackgroundColour 1768
+#define wxListItemAttr_SetFont 1769
+#define wxListItemAttr_SetTextColour 1770
+#define wxListItemAttr_destroy 1771
+#define wxImageList_new_0 1772
+#define wxImageList_new_3 1773
+#define wxImageList_Add_1 1774
+#define wxImageList_Add_2_0 1775
+#define wxImageList_Add_2_1 1776
+#define wxImageList_Create 1777
+#define wxImageList_Draw 1779
+#define wxImageList_GetBitmap 1780
+#define wxImageList_GetIcon 1781
+#define wxImageList_GetImageCount 1782
+#define wxImageList_GetSize 1783
+#define wxImageList_Remove 1784
+#define wxImageList_RemoveAll 1785
+#define wxImageList_Replace_2 1786
+#define wxImageList_Replace_3 1787
+#define wxImageList_destroy 1788
+#define wxTextAttr_new_0 1789
+#define wxTextAttr_new_2 1790
+#define wxTextAttr_GetAlignment 1791
+#define wxTextAttr_GetBackgroundColour 1792
+#define wxTextAttr_GetFont 1793
+#define wxTextAttr_GetLeftIndent 1794
+#define wxTextAttr_GetLeftSubIndent 1795
+#define wxTextAttr_GetRightIndent 1796
+#define wxTextAttr_GetTabs 1797
+#define wxTextAttr_GetTextColour 1798
+#define wxTextAttr_HasBackgroundColour 1799
+#define wxTextAttr_HasFont 1800
+#define wxTextAttr_HasTextColour 1801
+#define wxTextAttr_GetFlags 1802
+#define wxTextAttr_IsDefault 1803
+#define wxTextAttr_SetAlignment 1804
+#define wxTextAttr_SetBackgroundColour 1805
+#define wxTextAttr_SetFlags 1806
+#define wxTextAttr_SetFont 1807
+#define wxTextAttr_SetLeftIndent 1808
+#define wxTextAttr_SetRightIndent 1809
+#define wxTextAttr_SetTabs 1810
+#define wxTextAttr_SetTextColour 1811
+#define wxTextAttr_destroy 1812
+#define wxTextCtrl_new_3 1814
+#define wxTextCtrl_new_0 1815
+#define wxTextCtrl_destruct 1817
+#define wxTextCtrl_AppendText 1818
+#define wxTextCtrl_CanCopy 1819
+#define wxTextCtrl_CanCut 1820
+#define wxTextCtrl_CanPaste 1821
+#define wxTextCtrl_CanRedo 1822
+#define wxTextCtrl_CanUndo 1823
+#define wxTextCtrl_Clear 1824
+#define wxTextCtrl_Copy 1825
+#define wxTextCtrl_Create 1826
+#define wxTextCtrl_Cut 1827
+#define wxTextCtrl_DiscardEdits 1828
+#define wxTextCtrl_ChangeValue 1829
+#define wxTextCtrl_EmulateKeyPress 1830
+#define wxTextCtrl_GetDefaultStyle 1831
+#define wxTextCtrl_GetInsertionPoint 1832
+#define wxTextCtrl_GetLastPosition 1833
+#define wxTextCtrl_GetLineLength 1834
+#define wxTextCtrl_GetLineText 1835
+#define wxTextCtrl_GetNumberOfLines 1836
+#define wxTextCtrl_GetRange 1837
+#define wxTextCtrl_GetSelection 1838
+#define wxTextCtrl_GetStringSelection 1839
+#define wxTextCtrl_GetStyle 1840
+#define wxTextCtrl_GetValue 1841
+#define wxTextCtrl_IsEditable 1842
+#define wxTextCtrl_IsModified 1843
+#define wxTextCtrl_IsMultiLine 1844
+#define wxTextCtrl_IsSingleLine 1845
+#define wxTextCtrl_LoadFile 1846
+#define wxTextCtrl_MarkDirty 1847
+#define wxTextCtrl_Paste 1848
+#define wxTextCtrl_PositionToXY 1849
+#define wxTextCtrl_Redo 1850
+#define wxTextCtrl_Remove 1851
+#define wxTextCtrl_Replace 1852
+#define wxTextCtrl_SaveFile 1853
+#define wxTextCtrl_SetDefaultStyle 1854
+#define wxTextCtrl_SetEditable 1855
+#define wxTextCtrl_SetInsertionPoint 1856
+#define wxTextCtrl_SetInsertionPointEnd 1857
+#define wxTextCtrl_SetMaxLength 1859
+#define wxTextCtrl_SetSelection 1860
+#define wxTextCtrl_SetStyle 1861
+#define wxTextCtrl_SetValue 1862
+#define wxTextCtrl_ShowPosition 1863
+#define wxTextCtrl_Undo 1864
+#define wxTextCtrl_WriteText 1865
+#define wxTextCtrl_XYToPosition 1866
+#define wxNotebook_new_0 1869
+#define wxNotebook_new_3 1870
+#define wxNotebook_destruct 1871
+#define wxNotebook_AddPage 1872
+#define wxNotebook_AdvanceSelection 1873
+#define wxNotebook_AssignImageList 1874
+#define wxNotebook_Create 1875
+#define wxNotebook_DeleteAllPages 1876
+#define wxNotebook_DeletePage 1877
+#define wxNotebook_RemovePage 1878
+#define wxNotebook_GetCurrentPage 1879
+#define wxNotebook_GetImageList 1880
+#define wxNotebook_GetPage 1882
+#define wxNotebook_GetPageCount 1883
+#define wxNotebook_GetPageImage 1884
+#define wxNotebook_GetPageText 1885
+#define wxNotebook_GetRowCount 1886
+#define wxNotebook_GetSelection 1887
+#define wxNotebook_GetThemeBackgroundColour 1888
+#define wxNotebook_HitTest 1890
+#define wxNotebook_InsertPage 1892
+#define wxNotebook_SetImageList 1893
+#define wxNotebook_SetPadding 1894
+#define wxNotebook_SetPageSize 1895
+#define wxNotebook_SetPageImage 1896
+#define wxNotebook_SetPageText 1897
+#define wxNotebook_SetSelection 1898
+#define wxNotebook_ChangeSelection 1899
+#define wxChoicebook_new_0 1900
+#define wxChoicebook_new_3 1901
+#define wxChoicebook_AddPage 1902
+#define wxChoicebook_AdvanceSelection 1903
+#define wxChoicebook_AssignImageList 1904
+#define wxChoicebook_Create 1905
+#define wxChoicebook_DeleteAllPages 1906
+#define wxChoicebook_DeletePage 1907
+#define wxChoicebook_RemovePage 1908
+#define wxChoicebook_GetCurrentPage 1909
+#define wxChoicebook_GetImageList 1910
+#define wxChoicebook_GetPage 1912
+#define wxChoicebook_GetPageCount 1913
+#define wxChoicebook_GetPageImage 1914
+#define wxChoicebook_GetPageText 1915
+#define wxChoicebook_GetSelection 1916
+#define wxChoicebook_HitTest 1917
+#define wxChoicebook_InsertPage 1918
+#define wxChoicebook_SetImageList 1919
+#define wxChoicebook_SetPageSize 1920
+#define wxChoicebook_SetPageImage 1921
+#define wxChoicebook_SetPageText 1922
+#define wxChoicebook_SetSelection 1923
+#define wxChoicebook_ChangeSelection 1924
+#define wxChoicebook_destroy 1925
+#define wxToolbook_new_0 1926
+#define wxToolbook_new_3 1927
+#define wxToolbook_AddPage 1928
+#define wxToolbook_AdvanceSelection 1929
+#define wxToolbook_AssignImageList 1930
+#define wxToolbook_Create 1931
+#define wxToolbook_DeleteAllPages 1932
+#define wxToolbook_DeletePage 1933
+#define wxToolbook_RemovePage 1934
+#define wxToolbook_GetCurrentPage 1935
+#define wxToolbook_GetImageList 1936
+#define wxToolbook_GetPage 1938
+#define wxToolbook_GetPageCount 1939
+#define wxToolbook_GetPageImage 1940
+#define wxToolbook_GetPageText 1941
+#define wxToolbook_GetSelection 1942
+#define wxToolbook_HitTest 1944
+#define wxToolbook_InsertPage 1945
+#define wxToolbook_SetImageList 1946
+#define wxToolbook_SetPageSize 1947
+#define wxToolbook_SetPageImage 1948
+#define wxToolbook_SetPageText 1949
+#define wxToolbook_SetSelection 1950
+#define wxToolbook_ChangeSelection 1951
+#define wxToolbook_destroy 1952
+#define wxListbook_new_0 1953
+#define wxListbook_new_3 1954
+#define wxListbook_AddPage 1955
+#define wxListbook_AdvanceSelection 1956
+#define wxListbook_AssignImageList 1957
+#define wxListbook_Create 1958
+#define wxListbook_DeleteAllPages 1959
+#define wxListbook_DeletePage 1960
+#define wxListbook_RemovePage 1961
+#define wxListbook_GetCurrentPage 1962
+#define wxListbook_GetImageList 1963
+#define wxListbook_GetPage 1965
+#define wxListbook_GetPageCount 1966
+#define wxListbook_GetPageImage 1967
+#define wxListbook_GetPageText 1968
+#define wxListbook_GetSelection 1969
+#define wxListbook_HitTest 1971
+#define wxListbook_InsertPage 1972
+#define wxListbook_SetImageList 1973
+#define wxListbook_SetPageSize 1974
+#define wxListbook_SetPageImage 1975
+#define wxListbook_SetPageText 1976
+#define wxListbook_SetSelection 1977
+#define wxListbook_ChangeSelection 1978
+#define wxListbook_destroy 1979
+#define wxTreebook_new_0 1980
+#define wxTreebook_new_3 1981
+#define wxTreebook_AddPage 1982
+#define wxTreebook_AdvanceSelection 1983
+#define wxTreebook_AssignImageList 1984
+#define wxTreebook_Create 1985
+#define wxTreebook_DeleteAllPages 1986
+#define wxTreebook_DeletePage 1987
+#define wxTreebook_RemovePage 1988
+#define wxTreebook_GetCurrentPage 1989
+#define wxTreebook_GetImageList 1990
+#define wxTreebook_GetPage 1992
+#define wxTreebook_GetPageCount 1993
+#define wxTreebook_GetPageImage 1994
+#define wxTreebook_GetPageText 1995
+#define wxTreebook_GetSelection 1996
+#define wxTreebook_ExpandNode 1997
+#define wxTreebook_IsNodeExpanded 1998
+#define wxTreebook_HitTest 2000
+#define wxTreebook_InsertPage 2001
+#define wxTreebook_InsertSubPage 2002
+#define wxTreebook_SetImageList 2003
+#define wxTreebook_SetPageSize 2004
+#define wxTreebook_SetPageImage 2005
+#define wxTreebook_SetPageText 2006
+#define wxTreebook_SetSelection 2007
+#define wxTreebook_ChangeSelection 2008
+#define wxTreebook_destroy 2009
+#define wxTreeCtrl_new_2 2012
+#define wxTreeCtrl_new_0 2013
+#define wxTreeCtrl_destruct 2015
+#define wxTreeCtrl_AddRoot 2016
+#define wxTreeCtrl_AppendItem 2017
+#define wxTreeCtrl_AssignImageList 2018
+#define wxTreeCtrl_AssignStateImageList 2019
+#define wxTreeCtrl_Collapse 2020
+#define wxTreeCtrl_CollapseAndReset 2021
+#define wxTreeCtrl_Create 2022
+#define wxTreeCtrl_Delete 2023
+#define wxTreeCtrl_DeleteAllItems 2024
+#define wxTreeCtrl_DeleteChildren 2025
+#define wxTreeCtrl_EditLabel 2026
+#define wxTreeCtrl_EnsureVisible 2027
+#define wxTreeCtrl_Expand 2028
+#define wxTreeCtrl_GetBoundingRect 2029
+#define wxTreeCtrl_GetChildrenCount 2031
+#define wxTreeCtrl_GetCount 2032
+#define wxTreeCtrl_GetEditControl 2033
+#define wxTreeCtrl_GetFirstChild 2034
+#define wxTreeCtrl_GetNextChild 2035
+#define wxTreeCtrl_GetFirstVisibleItem 2036
+#define wxTreeCtrl_GetImageList 2037
+#define wxTreeCtrl_GetIndent 2038
+#define wxTreeCtrl_GetItemBackgroundColour 2039
+#define wxTreeCtrl_GetItemData 2040
+#define wxTreeCtrl_GetItemFont 2041
+#define wxTreeCtrl_GetItemImage_1 2042
+#define wxTreeCtrl_GetItemImage_2 2043
+#define wxTreeCtrl_GetItemText 2044
+#define wxTreeCtrl_GetItemTextColour 2045
+#define wxTreeCtrl_GetLastChild 2046
+#define wxTreeCtrl_GetNextSibling 2047
+#define wxTreeCtrl_GetNextVisible 2048
+#define wxTreeCtrl_GetItemParent 2049
+#define wxTreeCtrl_GetPrevSibling 2050
+#define wxTreeCtrl_GetPrevVisible 2051
+#define wxTreeCtrl_GetRootItem 2052
+#define wxTreeCtrl_GetSelection 2053
+#define wxTreeCtrl_GetSelections 2054
+#define wxTreeCtrl_GetStateImageList 2055
+#define wxTreeCtrl_HitTest 2056
+#define wxTreeCtrl_InsertItem 2058
+#define wxTreeCtrl_IsBold 2059
+#define wxTreeCtrl_IsExpanded 2060
+#define wxTreeCtrl_IsSelected 2061
+#define wxTreeCtrl_IsVisible 2062
+#define wxTreeCtrl_ItemHasChildren 2063
+#define wxTreeCtrl_IsTreeItemIdOk 2064
+#define wxTreeCtrl_PrependItem 2065
+#define wxTreeCtrl_ScrollTo 2066
+#define wxTreeCtrl_SelectItem_1 2067
+#define wxTreeCtrl_SelectItem_2 2068
+#define wxTreeCtrl_SetIndent 2069
+#define wxTreeCtrl_SetImageList 2070
+#define wxTreeCtrl_SetItemBackgroundColour 2071
+#define wxTreeCtrl_SetItemBold 2072
+#define wxTreeCtrl_SetItemData 2073
+#define wxTreeCtrl_SetItemDropHighlight 2074
+#define wxTreeCtrl_SetItemFont 2075
+#define wxTreeCtrl_SetItemHasChildren 2076
+#define wxTreeCtrl_SetItemImage_2 2077
+#define wxTreeCtrl_SetItemImage_3 2078
+#define wxTreeCtrl_SetItemText 2079
+#define wxTreeCtrl_SetItemTextColour 2080
+#define wxTreeCtrl_SetStateImageList 2081
+#define wxTreeCtrl_SetWindowStyle 2082
+#define wxTreeCtrl_SortChildren 2083
+#define wxTreeCtrl_Toggle 2084
+#define wxTreeCtrl_ToggleItemSelection 2085
+#define wxTreeCtrl_Unselect 2086
+#define wxTreeCtrl_UnselectAll 2087
+#define wxTreeCtrl_UnselectItem 2088
+#define wxScrollBar_new_0 2089
+#define wxScrollBar_new_3 2090
+#define wxScrollBar_destruct 2091
+#define wxScrollBar_Create 2092
+#define wxScrollBar_GetRange 2093
+#define wxScrollBar_GetPageSize 2094
+#define wxScrollBar_GetThumbPosition 2095
+#define wxScrollBar_GetThumbSize 2096
+#define wxScrollBar_SetThumbPosition 2097
+#define wxScrollBar_SetScrollbar 2098
+#define wxSpinButton_new_2 2100
+#define wxSpinButton_new_0 2101
+#define wxSpinButton_Create 2102
+#define wxSpinButton_GetMax 2103
+#define wxSpinButton_GetMin 2104
+#define wxSpinButton_GetValue 2105
+#define wxSpinButton_SetRange 2106
+#define wxSpinButton_SetValue 2107
+#define wxSpinButton_destroy 2108
+#define wxSpinCtrl_new_0 2109
+#define wxSpinCtrl_new_2 2110
+#define wxSpinCtrl_Create 2112
+#define wxSpinCtrl_SetValue_1_1 2115
+#define wxSpinCtrl_SetValue_1_0 2116
+#define wxSpinCtrl_GetValue 2118
+#define wxSpinCtrl_SetRange 2120
+#define wxSpinCtrl_SetSelection 2121
+#define wxSpinCtrl_GetMin 2123
+#define wxSpinCtrl_GetMax 2125
+#define wxSpinCtrl_destroy 2126
+#define wxStaticText_new_0 2127
+#define wxStaticText_new_4 2128
+#define wxStaticText_Create 2129
+#define wxStaticText_GetLabel 2130
+#define wxStaticText_SetLabel 2131
+#define wxStaticText_Wrap 2132
+#define wxStaticText_destroy 2133
+#define wxStaticBitmap_new_0 2134
+#define wxStaticBitmap_new_4 2135
+#define wxStaticBitmap_Create 2136
+#define wxStaticBitmap_GetBitmap 2137
+#define wxStaticBitmap_SetBitmap 2138
+#define wxStaticBitmap_destroy 2139
+#define wxRadioBox_new 2140
+#define wxRadioBox_destruct 2142
+#define wxRadioBox_Create 2143
+#define wxRadioBox_Enable_2 2144
+#define wxRadioBox_Enable_1 2145
+#define wxRadioBox_GetSelection 2146
+#define wxRadioBox_GetString 2147
+#define wxRadioBox_SetSelection 2148
+#define wxRadioBox_Show_2 2149
+#define wxRadioBox_Show_1 2150
+#define wxRadioBox_GetColumnCount 2151
+#define wxRadioBox_GetItemHelpText 2152
+#define wxRadioBox_GetItemToolTip 2153
+#define wxRadioBox_GetItemFromPoint 2155
+#define wxRadioBox_GetRowCount 2156
+#define wxRadioBox_IsItemEnabled 2157
+#define wxRadioBox_IsItemShown 2158
+#define wxRadioBox_SetItemHelpText 2159
+#define wxRadioBox_SetItemToolTip 2160
+#define wxRadioButton_new_0 2161
+#define wxRadioButton_new_4 2162
+#define wxRadioButton_Create 2163
+#define wxRadioButton_GetValue 2164
+#define wxRadioButton_SetValue 2165
+#define wxRadioButton_destroy 2166
+#define wxSlider_new_6 2168
+#define wxSlider_new_0 2169
+#define wxSlider_Create 2170
+#define wxSlider_GetLineSize 2171
+#define wxSlider_GetMax 2172
+#define wxSlider_GetMin 2173
+#define wxSlider_GetPageSize 2174
+#define wxSlider_GetThumbLength 2175
+#define wxSlider_GetValue 2176
+#define wxSlider_SetLineSize 2177
+#define wxSlider_SetPageSize 2178
+#define wxSlider_SetRange 2179
+#define wxSlider_SetThumbLength 2180
+#define wxSlider_SetValue 2181
+#define wxSlider_destroy 2182
+#define wxDialog_new_4 2184
+#define wxDialog_new_0 2185
+#define wxDialog_destruct 2187
+#define wxDialog_Create 2188
+#define wxDialog_CreateButtonSizer 2189
+#define wxDialog_CreateStdDialogButtonSizer 2190
+#define wxDialog_EndModal 2191
+#define wxDialog_GetAffirmativeId 2192
+#define wxDialog_GetReturnCode 2193
+#define wxDialog_IsModal 2194
+#define wxDialog_SetAffirmativeId 2195
+#define wxDialog_SetReturnCode 2196
+#define wxDialog_Show 2197
+#define wxDialog_ShowModal 2198
+#define wxColourDialog_new_0 2199
+#define wxColourDialog_new_2 2200
+#define wxColourDialog_destruct 2201
+#define wxColourDialog_Create 2202
+#define wxColourDialog_GetColourData 2203
+#define wxColourData_new_0 2204
+#define wxColourData_new_1 2205
+#define wxColourData_destruct 2206
+#define wxColourData_GetChooseFull 2207
+#define wxColourData_GetColour 2208
+#define wxColourData_GetCustomColour 2210
+#define wxColourData_SetChooseFull 2211
+#define wxColourData_SetColour 2212
+#define wxColourData_SetCustomColour 2213
+#define wxPalette_new_0 2214
+#define wxPalette_new_4 2215
+#define wxPalette_destruct 2217
+#define wxPalette_Create 2218
+#define wxPalette_GetColoursCount 2219
+#define wxPalette_GetPixel 2220
+#define wxPalette_GetRGB 2221
+#define wxPalette_IsOk 2222
+#define wxDirDialog_new 2226
+#define wxDirDialog_destruct 2227
+#define wxDirDialog_GetPath 2228
+#define wxDirDialog_GetMessage 2229
+#define wxDirDialog_SetMessage 2230
+#define wxDirDialog_SetPath 2231
+#define wxFileDialog_new 2235
+#define wxFileDialog_destruct 2236
+#define wxFileDialog_GetDirectory 2237
+#define wxFileDialog_GetFilename 2238
+#define wxFileDialog_GetFilenames 2239
+#define wxFileDialog_GetFilterIndex 2240
+#define wxFileDialog_GetMessage 2241
+#define wxFileDialog_GetPath 2242
+#define wxFileDialog_GetPaths 2243
+#define wxFileDialog_GetWildcard 2244
+#define wxFileDialog_SetDirectory 2245
+#define wxFileDialog_SetFilename 2246
+#define wxFileDialog_SetFilterIndex 2247
+#define wxFileDialog_SetMessage 2248
+#define wxFileDialog_SetPath 2249
+#define wxFileDialog_SetWildcard 2250
+#define wxPickerBase_SetInternalMargin 2251
+#define wxPickerBase_GetInternalMargin 2252
+#define wxPickerBase_SetTextCtrlProportion 2253
+#define wxPickerBase_SetPickerCtrlProportion 2254
+#define wxPickerBase_GetTextCtrlProportion 2255
+#define wxPickerBase_GetPickerCtrlProportion 2256
+#define wxPickerBase_HasTextCtrl 2257
+#define wxPickerBase_GetTextCtrl 2258
+#define wxPickerBase_IsTextCtrlGrowable 2259
+#define wxPickerBase_SetPickerCtrlGrowable 2260
+#define wxPickerBase_SetTextCtrlGrowable 2261
+#define wxPickerBase_IsPickerCtrlGrowable 2262
+#define wxFilePickerCtrl_new_0 2263
+#define wxFilePickerCtrl_new_3 2264
+#define wxFilePickerCtrl_Create 2265
+#define wxFilePickerCtrl_GetPath 2266
+#define wxFilePickerCtrl_SetPath 2267
+#define wxFilePickerCtrl_destroy 2268
+#define wxDirPickerCtrl_new_0 2269
+#define wxDirPickerCtrl_new_3 2270
+#define wxDirPickerCtrl_Create 2271
+#define wxDirPickerCtrl_GetPath 2272
+#define wxDirPickerCtrl_SetPath 2273
+#define wxDirPickerCtrl_destroy 2274
+#define wxColourPickerCtrl_new_0 2275
+#define wxColourPickerCtrl_new_3 2276
+#define wxColourPickerCtrl_Create 2277
+#define wxColourPickerCtrl_GetColour 2278
+#define wxColourPickerCtrl_SetColour_1_1 2279
+#define wxColourPickerCtrl_SetColour_1_0 2280
+#define wxColourPickerCtrl_destroy 2281
+#define wxDatePickerCtrl_new_0 2282
+#define wxDatePickerCtrl_new_3 2283
+#define wxDatePickerCtrl_GetRange 2284
+#define wxDatePickerCtrl_GetValue 2285
+#define wxDatePickerCtrl_SetRange 2286
+#define wxDatePickerCtrl_SetValue 2287
+#define wxDatePickerCtrl_destroy 2288
+#define wxFontPickerCtrl_new_0 2289
+#define wxFontPickerCtrl_new_3 2290
+#define wxFontPickerCtrl_Create 2291
+#define wxFontPickerCtrl_GetSelectedFont 2292
+#define wxFontPickerCtrl_SetSelectedFont 2293
+#define wxFontPickerCtrl_GetMaxPointSize 2294
+#define wxFontPickerCtrl_SetMaxPointSize 2295
+#define wxFontPickerCtrl_destroy 2296
+#define wxFindReplaceDialog_new_0 2299
+#define wxFindReplaceDialog_new_4 2300
+#define wxFindReplaceDialog_destruct 2301
+#define wxFindReplaceDialog_Create 2302
+#define wxFindReplaceDialog_GetData 2303
+#define wxFindReplaceData_new_0 2304
+#define wxFindReplaceData_new_1 2305
+#define wxFindReplaceData_GetFindString 2306
+#define wxFindReplaceData_GetReplaceString 2307
+#define wxFindReplaceData_GetFlags 2308
+#define wxFindReplaceData_SetFlags 2309
+#define wxFindReplaceData_SetFindString 2310
+#define wxFindReplaceData_SetReplaceString 2311
+#define wxFindReplaceData_destroy 2312
+#define wxMultiChoiceDialog_new_0 2313
+#define wxMultiChoiceDialog_new_5 2315
+#define wxMultiChoiceDialog_GetSelections 2316
+#define wxMultiChoiceDialog_SetSelections 2317
+#define wxMultiChoiceDialog_destroy 2318
+#define wxSingleChoiceDialog_new_0 2319
+#define wxSingleChoiceDialog_new_5 2321
+#define wxSingleChoiceDialog_GetSelection 2322
+#define wxSingleChoiceDialog_GetStringSelection 2323
+#define wxSingleChoiceDialog_SetSelection 2324
+#define wxSingleChoiceDialog_destroy 2325
+#define wxTextEntryDialog_new 2326
+#define wxTextEntryDialog_GetValue 2327
+#define wxTextEntryDialog_SetValue 2328
+#define wxTextEntryDialog_destroy 2329
+#define wxPasswordEntryDialog_new 2330
+#define wxPasswordEntryDialog_destroy 2331
+#define wxFontData_new_0 2332
+#define wxFontData_new_1 2333
+#define wxFontData_destruct 2334
+#define wxFontData_EnableEffects 2335
+#define wxFontData_GetAllowSymbols 2336
+#define wxFontData_GetColour 2337
+#define wxFontData_GetChosenFont 2338
+#define wxFontData_GetEnableEffects 2339
+#define wxFontData_GetInitialFont 2340
+#define wxFontData_GetShowHelp 2341
+#define wxFontData_SetAllowSymbols 2342
+#define wxFontData_SetChosenFont 2343
+#define wxFontData_SetColour 2344
+#define wxFontData_SetInitialFont 2345
+#define wxFontData_SetRange 2346
+#define wxFontData_SetShowHelp 2347
+#define wxFontDialog_new_0 2351
+#define wxFontDialog_new_2 2353
+#define wxFontDialog_Create 2355
+#define wxFontDialog_GetFontData 2356
+#define wxFontDialog_destroy 2358
+#define wxProgressDialog_new 2359
+#define wxProgressDialog_destruct 2360
+#define wxProgressDialog_Resume 2361
+#define wxProgressDialog_Update_2 2362
+#define wxProgressDialog_Update_0 2363
+#define wxMessageDialog_new 2364
+#define wxMessageDialog_destruct 2365
+#define wxPageSetupDialog_new 2366
+#define wxPageSetupDialog_destruct 2367
+#define wxPageSetupDialog_GetPageSetupData 2368
+#define wxPageSetupDialog_ShowModal 2369
+#define wxPageSetupDialogData_new_0 2370
+#define wxPageSetupDialogData_new_1_0 2371
+#define wxPageSetupDialogData_new_1_1 2372
+#define wxPageSetupDialogData_destruct 2373
+#define wxPageSetupDialogData_EnableHelp 2374
+#define wxPageSetupDialogData_EnableMargins 2375
+#define wxPageSetupDialogData_EnableOrientation 2376
+#define wxPageSetupDialogData_EnablePaper 2377
+#define wxPageSetupDialogData_EnablePrinter 2378
+#define wxPageSetupDialogData_GetDefaultMinMargins 2379
+#define wxPageSetupDialogData_GetEnableMargins 2380
+#define wxPageSetupDialogData_GetEnableOrientation 2381
+#define wxPageSetupDialogData_GetEnablePaper 2382
+#define wxPageSetupDialogData_GetEnablePrinter 2383
+#define wxPageSetupDialogData_GetEnableHelp 2384
+#define wxPageSetupDialogData_GetDefaultInfo 2385
+#define wxPageSetupDialogData_GetMarginTopLeft 2386
+#define wxPageSetupDialogData_GetMarginBottomRight 2387
+#define wxPageSetupDialogData_GetMinMarginTopLeft 2388
+#define wxPageSetupDialogData_GetMinMarginBottomRight 2389
+#define wxPageSetupDialogData_GetPaperId 2390
+#define wxPageSetupDialogData_GetPaperSize 2391
+#define wxPageSetupDialogData_GetPrintData 2393
+#define wxPageSetupDialogData_IsOk 2394
+#define wxPageSetupDialogData_SetDefaultInfo 2395
+#define wxPageSetupDialogData_SetDefaultMinMargins 2396
+#define wxPageSetupDialogData_SetMarginTopLeft 2397
+#define wxPageSetupDialogData_SetMarginBottomRight 2398
+#define wxPageSetupDialogData_SetMinMarginTopLeft 2399
+#define wxPageSetupDialogData_SetMinMarginBottomRight 2400
+#define wxPageSetupDialogData_SetPaperId 2401
+#define wxPageSetupDialogData_SetPaperSize_1_1 2402
+#define wxPageSetupDialogData_SetPaperSize_1_0 2403
+#define wxPageSetupDialogData_SetPrintData 2404
+#define wxPrintDialog_new_2_0 2405
+#define wxPrintDialog_new_2_1 2406
+#define wxPrintDialog_destruct 2407
+#define wxPrintDialog_GetPrintDialogData 2408
+#define wxPrintDialog_GetPrintDC 2409
+#define wxPrintDialogData_new_0 2410
+#define wxPrintDialogData_new_1_1 2411
+#define wxPrintDialogData_new_1_0 2412
+#define wxPrintDialogData_destruct 2413
+#define wxPrintDialogData_EnableHelp 2414
+#define wxPrintDialogData_EnablePageNumbers 2415
+#define wxPrintDialogData_EnablePrintToFile 2416
+#define wxPrintDialogData_EnableSelection 2417
+#define wxPrintDialogData_GetAllPages 2418
+#define wxPrintDialogData_GetCollate 2419
+#define wxPrintDialogData_GetFromPage 2420
+#define wxPrintDialogData_GetMaxPage 2421
+#define wxPrintDialogData_GetMinPage 2422
+#define wxPrintDialogData_GetNoCopies 2423
+#define wxPrintDialogData_GetPrintData 2424
+#define wxPrintDialogData_GetPrintToFile 2425
+#define wxPrintDialogData_GetSelection 2426
+#define wxPrintDialogData_GetToPage 2427
+#define wxPrintDialogData_IsOk 2428
+#define wxPrintDialogData_SetCollate 2429
+#define wxPrintDialogData_SetFromPage 2430
+#define wxPrintDialogData_SetMaxPage 2431
+#define wxPrintDialogData_SetMinPage 2432
+#define wxPrintDialogData_SetNoCopies 2433
+#define wxPrintDialogData_SetPrintData 2434
+#define wxPrintDialogData_SetPrintToFile 2435
+#define wxPrintDialogData_SetSelection 2436
+#define wxPrintDialogData_SetToPage 2437
+#define wxPrintData_new_0 2438
+#define wxPrintData_new_1 2439
+#define wxPrintData_destruct 2440
+#define wxPrintData_GetCollate 2441
+#define wxPrintData_GetBin 2442
+#define wxPrintData_GetColour 2443
+#define wxPrintData_GetDuplex 2444
+#define wxPrintData_GetNoCopies 2445
+#define wxPrintData_GetOrientation 2446
+#define wxPrintData_GetPaperId 2447
+#define wxPrintData_GetPrinterName 2448
+#define wxPrintData_GetQuality 2449
+#define wxPrintData_IsOk 2450
+#define wxPrintData_SetBin 2451
+#define wxPrintData_SetCollate 2452
+#define wxPrintData_SetColour 2453
+#define wxPrintData_SetDuplex 2454
+#define wxPrintData_SetNoCopies 2455
+#define wxPrintData_SetOrientation 2456
+#define wxPrintData_SetPaperId 2457
+#define wxPrintData_SetPrinterName 2458
+#define wxPrintData_SetQuality 2459
+#define wxPrintPreview_new_2 2462
+#define wxPrintPreview_new_3 2463
+#define wxPrintPreview_destruct 2465
+#define wxPrintPreview_GetCanvas 2466
+#define wxPrintPreview_GetCurrentPage 2467
+#define wxPrintPreview_GetFrame 2468
+#define wxPrintPreview_GetMaxPage 2469
+#define wxPrintPreview_GetMinPage 2470
+#define wxPrintPreview_GetPrintout 2471
+#define wxPrintPreview_GetPrintoutForPrinting 2472
+#define wxPrintPreview_IsOk 2473
+#define wxPrintPreview_PaintPage 2474
+#define wxPrintPreview_Print 2475
+#define wxPrintPreview_RenderPage 2476
+#define wxPrintPreview_SetCanvas 2477
+#define wxPrintPreview_SetCurrentPage 2478
+#define wxPrintPreview_SetFrame 2479
+#define wxPrintPreview_SetPrintout 2480
+#define wxPrintPreview_SetZoom 2481
+#define wxPreviewFrame_new 2482
+#define wxPreviewFrame_destruct 2483
+#define wxPreviewFrame_CreateControlBar 2484
+#define wxPreviewFrame_CreateCanvas 2485
+#define wxPreviewFrame_Initialize 2486
+#define wxPreviewFrame_OnCloseWindow 2487
+#define wxPreviewControlBar_new 2488
+#define wxPreviewControlBar_destruct 2489
+#define wxPreviewControlBar_CreateButtons 2490
+#define wxPreviewControlBar_GetPrintPreview 2491
+#define wxPreviewControlBar_GetZoomControl 2492
+#define wxPreviewControlBar_SetZoomControl 2493
+#define wxPrinter_new 2495
+#define wxPrinter_CreateAbortWindow 2496
+#define wxPrinter_GetAbort 2497
+#define wxPrinter_GetLastError 2498
+#define wxPrinter_GetPrintDialogData 2499
+#define wxPrinter_Print 2500
+#define wxPrinter_PrintDialog 2501
+#define wxPrinter_ReportError 2502
+#define wxPrinter_Setup 2503
+#define wxPrinter_destroy 2504
+#define wxXmlResource_new_1 2505
+#define wxXmlResource_new_2 2506
+#define wxXmlResource_destruct 2507
+#define wxXmlResource_AttachUnknownControl 2508
+#define wxXmlResource_ClearHandlers 2509
+#define wxXmlResource_CompareVersion 2510
+#define wxXmlResource_Get 2511
+#define wxXmlResource_GetFlags 2512
+#define wxXmlResource_GetVersion 2513
+#define wxXmlResource_GetXRCID 2514
+#define wxXmlResource_InitAllHandlers 2515
+#define wxXmlResource_Load 2516
+#define wxXmlResource_LoadBitmap 2517
+#define wxXmlResource_LoadDialog_2 2518
+#define wxXmlResource_LoadDialog_3 2519
+#define wxXmlResource_LoadFrame_2 2520
+#define wxXmlResource_LoadFrame_3 2521
+#define wxXmlResource_LoadIcon 2522
+#define wxXmlResource_LoadMenu 2523
+#define wxXmlResource_LoadMenuBar_2 2524
+#define wxXmlResource_LoadMenuBar_1 2525
+#define wxXmlResource_LoadPanel_2 2526
+#define wxXmlResource_LoadPanel_3 2527
+#define wxXmlResource_LoadToolBar 2528
+#define wxXmlResource_Set 2529
+#define wxXmlResource_SetFlags 2530
+#define wxXmlResource_Unload 2531
+#define wxXmlResource_xrcctrl 2532
+#define wxHtmlEasyPrinting_new 2533
+#define wxHtmlEasyPrinting_destruct 2534
+#define wxHtmlEasyPrinting_GetPrintData 2535
+#define wxHtmlEasyPrinting_GetPageSetupData 2536
+#define wxHtmlEasyPrinting_PreviewFile 2537
+#define wxHtmlEasyPrinting_PreviewText 2538
+#define wxHtmlEasyPrinting_PrintFile 2539
+#define wxHtmlEasyPrinting_PrintText 2540
+#define wxHtmlEasyPrinting_PageSetup 2541
+#define wxHtmlEasyPrinting_SetFonts 2542
+#define wxHtmlEasyPrinting_SetHeader 2543
+#define wxHtmlEasyPrinting_SetFooter 2544
+#define wxGLCanvas_new_2 2546
+#define wxGLCanvas_new_3_1 2547
+#define wxGLCanvas_new_3_0 2548
+#define wxGLCanvas_GetContext 2549
+#define wxGLCanvas_SetCurrent 2551
+#define wxGLCanvas_SwapBuffers 2552
+#define wxGLCanvas_destroy 2553
+#define wxAuiManager_new 2554
+#define wxAuiManager_destruct 2555
+#define wxAuiManager_AddPane_2_1 2556
+#define wxAuiManager_AddPane_3 2557
+#define wxAuiManager_AddPane_2_0 2558
+#define wxAuiManager_DetachPane 2559
+#define wxAuiManager_GetAllPanes 2560
+#define wxAuiManager_GetArtProvider 2561
+#define wxAuiManager_GetDockSizeConstraint 2562
+#define wxAuiManager_GetFlags 2563
+#define wxAuiManager_GetManagedWindow 2564
+#define wxAuiManager_GetManager 2565
+#define wxAuiManager_GetPane_1_1 2566
+#define wxAuiManager_GetPane_1_0 2567
+#define wxAuiManager_HideHint 2568
+#define wxAuiManager_InsertPane 2569
+#define wxAuiManager_LoadPaneInfo 2570
+#define wxAuiManager_LoadPerspective 2571
+#define wxAuiManager_SavePaneInfo 2572
+#define wxAuiManager_SavePerspective 2573
+#define wxAuiManager_SetArtProvider 2574
+#define wxAuiManager_SetDockSizeConstraint 2575
+#define wxAuiManager_SetFlags 2576
+#define wxAuiManager_SetManagedWindow 2577
+#define wxAuiManager_ShowHint 2578
+#define wxAuiManager_UnInit 2579
+#define wxAuiManager_Update 2580
+#define wxAuiPaneInfo_new_0 2581
+#define wxAuiPaneInfo_new_1 2582
+#define wxAuiPaneInfo_destruct 2583
+#define wxAuiPaneInfo_BestSize_1 2584
+#define wxAuiPaneInfo_BestSize_2 2585
+#define wxAuiPaneInfo_Bottom 2586
+#define wxAuiPaneInfo_BottomDockable 2587
+#define wxAuiPaneInfo_Caption 2588
+#define wxAuiPaneInfo_CaptionVisible 2589
+#define wxAuiPaneInfo_Centre 2590
+#define wxAuiPaneInfo_CentrePane 2591
+#define wxAuiPaneInfo_CloseButton 2592
+#define wxAuiPaneInfo_DefaultPane 2593
+#define wxAuiPaneInfo_DestroyOnClose 2594
+#define wxAuiPaneInfo_Direction 2595
+#define wxAuiPaneInfo_Dock 2596
+#define wxAuiPaneInfo_Dockable 2597
+#define wxAuiPaneInfo_Fixed 2598
+#define wxAuiPaneInfo_Float 2599
+#define wxAuiPaneInfo_Floatable 2600
+#define wxAuiPaneInfo_FloatingPosition_1 2601
+#define wxAuiPaneInfo_FloatingPosition_2 2602
+#define wxAuiPaneInfo_FloatingSize_1 2603
+#define wxAuiPaneInfo_FloatingSize_2 2604
+#define wxAuiPaneInfo_Gripper 2605
+#define wxAuiPaneInfo_GripperTop 2606
+#define wxAuiPaneInfo_HasBorder 2607
+#define wxAuiPaneInfo_HasCaption 2608
+#define wxAuiPaneInfo_HasCloseButton 2609
+#define wxAuiPaneInfo_HasFlag 2610
+#define wxAuiPaneInfo_HasGripper 2611
+#define wxAuiPaneInfo_HasGripperTop 2612
+#define wxAuiPaneInfo_HasMaximizeButton 2613
+#define wxAuiPaneInfo_HasMinimizeButton 2614
+#define wxAuiPaneInfo_HasPinButton 2615
+#define wxAuiPaneInfo_Hide 2616
+#define wxAuiPaneInfo_IsBottomDockable 2617
+#define wxAuiPaneInfo_IsDocked 2618
+#define wxAuiPaneInfo_IsFixed 2619
+#define wxAuiPaneInfo_IsFloatable 2620
+#define wxAuiPaneInfo_IsFloating 2621
+#define wxAuiPaneInfo_IsLeftDockable 2622
+#define wxAuiPaneInfo_IsMovable 2623
+#define wxAuiPaneInfo_IsOk 2624
+#define wxAuiPaneInfo_IsResizable 2625
+#define wxAuiPaneInfo_IsRightDockable 2626
+#define wxAuiPaneInfo_IsShown 2627
+#define wxAuiPaneInfo_IsToolbar 2628
+#define wxAuiPaneInfo_IsTopDockable 2629
+#define wxAuiPaneInfo_Layer 2630
+#define wxAuiPaneInfo_Left 2631
+#define wxAuiPaneInfo_LeftDockable 2632
+#define wxAuiPaneInfo_MaxSize_1 2633
+#define wxAuiPaneInfo_MaxSize_2 2634
+#define wxAuiPaneInfo_MaximizeButton 2635
+#define wxAuiPaneInfo_MinSize_1 2636
+#define wxAuiPaneInfo_MinSize_2 2637
+#define wxAuiPaneInfo_MinimizeButton 2638
+#define wxAuiPaneInfo_Movable 2639
+#define wxAuiPaneInfo_Name 2640
+#define wxAuiPaneInfo_PaneBorder 2641
+#define wxAuiPaneInfo_PinButton 2642
+#define wxAuiPaneInfo_Position 2643
+#define wxAuiPaneInfo_Resizable 2644
+#define wxAuiPaneInfo_Right 2645
+#define wxAuiPaneInfo_RightDockable 2646
+#define wxAuiPaneInfo_Row 2647
+#define wxAuiPaneInfo_SafeSet 2648
+#define wxAuiPaneInfo_SetFlag 2649
+#define wxAuiPaneInfo_Show 2650
+#define wxAuiPaneInfo_ToolbarPane 2651
+#define wxAuiPaneInfo_Top 2652
+#define wxAuiPaneInfo_TopDockable 2653
+#define wxAuiPaneInfo_Window 2654
+#define wxAuiPaneInfo_GetWindow 2655
+#define wxAuiPaneInfo_GetFrame 2656
+#define wxAuiPaneInfo_GetDirection 2657
+#define wxAuiPaneInfo_GetLayer 2658
+#define wxAuiPaneInfo_GetRow 2659
+#define wxAuiPaneInfo_GetPosition 2660
+#define wxAuiPaneInfo_GetFloatingPosition 2661
+#define wxAuiPaneInfo_GetFloatingSize 2662
+#define wxAuiNotebook_new_0 2663
+#define wxAuiNotebook_new_2 2664
+#define wxAuiNotebook_AddPage 2665
+#define wxAuiNotebook_Create 2666
+#define wxAuiNotebook_DeletePage 2667
+#define wxAuiNotebook_GetArtProvider 2668
+#define wxAuiNotebook_GetPage 2669
+#define wxAuiNotebook_GetPageBitmap 2670
+#define wxAuiNotebook_GetPageCount 2671
+#define wxAuiNotebook_GetPageIndex 2672
+#define wxAuiNotebook_GetPageText 2673
+#define wxAuiNotebook_GetSelection 2674
+#define wxAuiNotebook_InsertPage 2675
+#define wxAuiNotebook_RemovePage 2676
+#define wxAuiNotebook_SetArtProvider 2677
+#define wxAuiNotebook_SetFont 2678
+#define wxAuiNotebook_SetPageBitmap 2679
+#define wxAuiNotebook_SetPageText 2680
+#define wxAuiNotebook_SetSelection 2681
+#define wxAuiNotebook_SetTabCtrlHeight 2682
+#define wxAuiNotebook_SetUniformBitmapSize 2683
+#define wxAuiNotebook_destroy 2684
+#define wxAuiTabArt_SetFlags 2685
+#define wxAuiTabArt_SetMeasuringFont 2686
+#define wxAuiTabArt_SetNormalFont 2687
+#define wxAuiTabArt_SetSelectedFont 2688
+#define wxAuiTabArt_SetColour 2689
+#define wxAuiTabArt_SetActiveColour 2690
+#define wxAuiDockArt_GetColour 2691
+#define wxAuiDockArt_GetFont 2692
+#define wxAuiDockArt_GetMetric 2693
+#define wxAuiDockArt_SetColour 2694
+#define wxAuiDockArt_SetFont 2695
+#define wxAuiDockArt_SetMetric 2696
+#define wxAuiSimpleTabArt_new 2697
+#define wxAuiSimpleTabArt_destroy 2698
+#define wxMDIParentFrame_new_0 2699
+#define wxMDIParentFrame_new_4 2700
+#define wxMDIParentFrame_destruct 2701
+#define wxMDIParentFrame_ActivateNext 2702
+#define wxMDIParentFrame_ActivatePrevious 2703
+#define wxMDIParentFrame_ArrangeIcons 2704
+#define wxMDIParentFrame_Cascade 2705
+#define wxMDIParentFrame_Create 2706
+#define wxMDIParentFrame_GetActiveChild 2707
+#define wxMDIParentFrame_GetClientWindow 2708
+#define wxMDIParentFrame_Tile 2709
+#define wxMDIChildFrame_new_0 2710
+#define wxMDIChildFrame_new_4 2711
+#define wxMDIChildFrame_destruct 2712
+#define wxMDIChildFrame_Activate 2713
+#define wxMDIChildFrame_Create 2714
+#define wxMDIChildFrame_Maximize 2715
+#define wxMDIChildFrame_Restore 2716
+#define wxMDIClientWindow_new_0 2717
+#define wxMDIClientWindow_new_2 2718
+#define wxMDIClientWindow_destruct 2719
+#define wxMDIClientWindow_CreateClient 2720
+#define wxLayoutAlgorithm_new 2721
+#define wxLayoutAlgorithm_LayoutFrame 2722
+#define wxLayoutAlgorithm_LayoutMDIFrame 2723
+#define wxLayoutAlgorithm_LayoutWindow 2724
+#define wxLayoutAlgorithm_destroy 2725
+#define wxEvent_GetId 2726
+#define wxEvent_GetSkipped 2727
+#define wxEvent_GetTimestamp 2728
+#define wxEvent_IsCommandEvent 2729
+#define wxEvent_ResumePropagation 2730
+#define wxEvent_ShouldPropagate 2731
+#define wxEvent_Skip 2732
+#define wxEvent_StopPropagation 2733
+#define wxCommandEvent_getClientData 2734
+#define wxCommandEvent_GetExtraLong 2735
+#define wxCommandEvent_GetInt 2736
+#define wxCommandEvent_GetSelection 2737
+#define wxCommandEvent_GetString 2738
+#define wxCommandEvent_IsChecked 2739
+#define wxCommandEvent_IsSelection 2740
+#define wxCommandEvent_SetInt 2741
+#define wxCommandEvent_SetString 2742
+#define wxScrollEvent_GetOrientation 2743
+#define wxScrollEvent_GetPosition 2744
+#define wxScrollWinEvent_GetOrientation 2745
+#define wxScrollWinEvent_GetPosition 2746
+#define wxMouseEvent_AltDown 2747
+#define wxMouseEvent_Button 2748
+#define wxMouseEvent_ButtonDClick 2749
+#define wxMouseEvent_ButtonDown 2750
+#define wxMouseEvent_ButtonUp 2751
+#define wxMouseEvent_CmdDown 2752
+#define wxMouseEvent_ControlDown 2753
+#define wxMouseEvent_Dragging 2754
+#define wxMouseEvent_Entering 2755
+#define wxMouseEvent_GetButton 2756
+#define wxMouseEvent_GetPosition 2759
+#define wxMouseEvent_GetLogicalPosition 2760
+#define wxMouseEvent_GetLinesPerAction 2761
+#define wxMouseEvent_GetWheelRotation 2762
+#define wxMouseEvent_GetWheelDelta 2763
+#define wxMouseEvent_GetX 2764
+#define wxMouseEvent_GetY 2765
+#define wxMouseEvent_IsButton 2766
+#define wxMouseEvent_IsPageScroll 2767
+#define wxMouseEvent_Leaving 2768
+#define wxMouseEvent_LeftDClick 2769
+#define wxMouseEvent_LeftDown 2770
+#define wxMouseEvent_LeftIsDown 2771
+#define wxMouseEvent_LeftUp 2772
+#define wxMouseEvent_MetaDown 2773
+#define wxMouseEvent_MiddleDClick 2774
+#define wxMouseEvent_MiddleDown 2775
+#define wxMouseEvent_MiddleIsDown 2776
+#define wxMouseEvent_MiddleUp 2777
+#define wxMouseEvent_Moving 2778
+#define wxMouseEvent_RightDClick 2779
+#define wxMouseEvent_RightDown 2780
+#define wxMouseEvent_RightIsDown 2781
+#define wxMouseEvent_RightUp 2782
+#define wxMouseEvent_ShiftDown 2783
+#define wxSetCursorEvent_GetCursor 2784
+#define wxSetCursorEvent_GetX 2785
+#define wxSetCursorEvent_GetY 2786
+#define wxSetCursorEvent_HasCursor 2787
+#define wxSetCursorEvent_SetCursor 2788
+#define wxKeyEvent_AltDown 2789
+#define wxKeyEvent_CmdDown 2790
+#define wxKeyEvent_ControlDown 2791
+#define wxKeyEvent_GetKeyCode 2792
+#define wxKeyEvent_GetModifiers 2793
+#define wxKeyEvent_GetPosition 2796
+#define wxKeyEvent_GetRawKeyCode 2797
+#define wxKeyEvent_GetRawKeyFlags 2798
+#define wxKeyEvent_GetUnicodeKey 2799
+#define wxKeyEvent_GetX 2800
+#define wxKeyEvent_GetY 2801
+#define wxKeyEvent_HasModifiers 2802
+#define wxKeyEvent_MetaDown 2803
+#define wxKeyEvent_ShiftDown 2804
+#define wxSizeEvent_GetSize 2805
+#define wxMoveEvent_GetPosition 2806
+#define wxEraseEvent_GetDC 2807
+#define wxFocusEvent_GetWindow 2808
+#define wxChildFocusEvent_GetWindow 2809
+#define wxMenuEvent_GetMenu 2810
+#define wxMenuEvent_GetMenuId 2811
+#define wxMenuEvent_IsPopup 2812
+#define wxCloseEvent_CanVeto 2813
+#define wxCloseEvent_GetLoggingOff 2814
+#define wxCloseEvent_SetCanVeto 2815
+#define wxCloseEvent_SetLoggingOff 2816
+#define wxCloseEvent_Veto 2817
+#define wxShowEvent_SetShow 2818
+#define wxShowEvent_GetShow 2819
+#define wxIconizeEvent_Iconized 2820
+#define wxJoystickEvent_ButtonDown 2821
+#define wxJoystickEvent_ButtonIsDown 2822
+#define wxJoystickEvent_ButtonUp 2823
+#define wxJoystickEvent_GetButtonChange 2824
+#define wxJoystickEvent_GetButtonState 2825
+#define wxJoystickEvent_GetJoystick 2826
+#define wxJoystickEvent_GetPosition 2827
+#define wxJoystickEvent_GetZPosition 2828
+#define wxJoystickEvent_IsButton 2829
+#define wxJoystickEvent_IsMove 2830
+#define wxJoystickEvent_IsZMove 2831
+#define wxUpdateUIEvent_CanUpdate 2832
+#define wxUpdateUIEvent_Check 2833
+#define wxUpdateUIEvent_Enable 2834
+#define wxUpdateUIEvent_Show 2835
+#define wxUpdateUIEvent_GetChecked 2836
+#define wxUpdateUIEvent_GetEnabled 2837
+#define wxUpdateUIEvent_GetShown 2838
+#define wxUpdateUIEvent_GetSetChecked 2839
+#define wxUpdateUIEvent_GetSetEnabled 2840
+#define wxUpdateUIEvent_GetSetShown 2841
+#define wxUpdateUIEvent_GetSetText 2842
+#define wxUpdateUIEvent_GetText 2843
+#define wxUpdateUIEvent_GetMode 2844
+#define wxUpdateUIEvent_GetUpdateInterval 2845
+#define wxUpdateUIEvent_ResetUpdateTime 2846
+#define wxUpdateUIEvent_SetMode 2847
+#define wxUpdateUIEvent_SetText 2848
+#define wxUpdateUIEvent_SetUpdateInterval 2849
+#define wxMouseCaptureChangedEvent_GetCapturedWindow 2850
+#define wxPaletteChangedEvent_SetChangedWindow 2851
+#define wxPaletteChangedEvent_GetChangedWindow 2852
+#define wxQueryNewPaletteEvent_SetPaletteRealized 2853
+#define wxQueryNewPaletteEvent_GetPaletteRealized 2854
+#define wxNavigationKeyEvent_GetDirection 2855
+#define wxNavigationKeyEvent_SetDirection 2856
+#define wxNavigationKeyEvent_IsWindowChange 2857
+#define wxNavigationKeyEvent_SetWindowChange 2858
+#define wxNavigationKeyEvent_IsFromTab 2859
+#define wxNavigationKeyEvent_SetFromTab 2860
+#define wxNavigationKeyEvent_GetCurrentFocus 2861
+#define wxNavigationKeyEvent_SetCurrentFocus 2862
+#define wxHelpEvent_GetOrigin 2863
+#define wxHelpEvent_GetPosition 2864
+#define wxHelpEvent_SetOrigin 2865
+#define wxHelpEvent_SetPosition 2866
+#define wxContextMenuEvent_GetPosition 2867
+#define wxContextMenuEvent_SetPosition 2868
+#define wxIdleEvent_CanSend 2869
+#define wxIdleEvent_GetMode 2870
+#define wxIdleEvent_RequestMore 2871
+#define wxIdleEvent_MoreRequested 2872
+#define wxIdleEvent_SetMode 2873
+#define wxGridEvent_AltDown 2874
+#define wxGridEvent_ControlDown 2875
+#define wxGridEvent_GetCol 2876
+#define wxGridEvent_GetPosition 2877
+#define wxGridEvent_GetRow 2878
+#define wxGridEvent_MetaDown 2879
+#define wxGridEvent_Selecting 2880
+#define wxGridEvent_ShiftDown 2881
+#define wxNotifyEvent_Allow 2882
+#define wxNotifyEvent_IsAllowed 2883
+#define wxNotifyEvent_Veto 2884
+#define wxSashEvent_GetEdge 2885
+#define wxSashEvent_GetDragRect 2886
+#define wxSashEvent_GetDragStatus 2887
+#define wxListEvent_GetCacheFrom 2888
+#define wxListEvent_GetCacheTo 2889
+#define wxListEvent_GetKeyCode 2890
+#define wxListEvent_GetIndex 2891
+#define wxListEvent_GetColumn 2892
+#define wxListEvent_GetPoint 2893
+#define wxListEvent_GetLabel 2894
+#define wxListEvent_GetText 2895
+#define wxListEvent_GetImage 2896
+#define wxListEvent_GetData 2897
+#define wxListEvent_GetMask 2898
+#define wxListEvent_GetItem 2899
+#define wxListEvent_IsEditCancelled 2900
+#define wxDateEvent_GetDate 2901
+#define wxCalendarEvent_GetWeekDay 2902
+#define wxFileDirPickerEvent_GetPath 2903
+#define wxColourPickerEvent_GetColour 2904
+#define wxFontPickerEvent_GetFont 2905
+#define wxStyledTextEvent_GetPosition 2906
+#define wxStyledTextEvent_GetKey 2907
+#define wxStyledTextEvent_GetModifiers 2908
+#define wxStyledTextEvent_GetModificationType 2909
+#define wxStyledTextEvent_GetText 2910
+#define wxStyledTextEvent_GetLength 2911
+#define wxStyledTextEvent_GetLinesAdded 2912
+#define wxStyledTextEvent_GetLine 2913
+#define wxStyledTextEvent_GetFoldLevelNow 2914
+#define wxStyledTextEvent_GetFoldLevelPrev 2915
+#define wxStyledTextEvent_GetMargin 2916
+#define wxStyledTextEvent_GetMessage 2917
+#define wxStyledTextEvent_GetWParam 2918
+#define wxStyledTextEvent_GetLParam 2919
+#define wxStyledTextEvent_GetListType 2920
+#define wxStyledTextEvent_GetX 2921
+#define wxStyledTextEvent_GetY 2922
+#define wxStyledTextEvent_GetDragText 2923
+#define wxStyledTextEvent_GetDragAllowMove 2924
+#define wxStyledTextEvent_GetDragResult 2925
+#define wxStyledTextEvent_GetShift 2926
+#define wxStyledTextEvent_GetControl 2927
+#define wxStyledTextEvent_GetAlt 2928
+#define utils_wxGetKeyState 2929
+#define utils_wxGetMousePosition 2930
+#define utils_wxGetMouseState 2931
+#define utils_wxSetDetectableAutoRepeat 2932
+#define utils_wxBell 2933
+#define utils_wxFindMenuItemId 2934
+#define utils_wxGenericFindWindowAtPoint 2935
+#define utils_wxFindWindowAtPoint 2936
+#define utils_wxBeginBusyCursor 2937
+#define utils_wxEndBusyCursor 2938
+#define utils_wxIsBusy 2939
+#define utils_wxShutdown 2940
+#define utils_wxShell 2941
+#define utils_wxLaunchDefaultBrowser 2942
+#define utils_wxGetEmailAddress 2943
+#define utils_wxGetUserId 2944
+#define utils_wxGetHomeDir 2945
+#define utils_wxNewId 2946
+#define utils_wxRegisterId 2947
+#define utils_wxGetCurrentId 2948
+#define utils_wxGetOsDescription 2949
+#define utils_wxIsPlatformLittleEndian 2950
+#define utils_wxIsPlatform64Bit 2951
+#define gdicmn_wxDisplaySize 2952
+#define gdicmn_wxSetCursor 2953
+#define wxPrintout_new 2954
+#define wxPrintout_destruct 2955
+#define wxPrintout_GetDC 2956
+#define wxPrintout_GetPageSizeMM 2957
+#define wxPrintout_GetPageSizePixels 2958
+#define wxPrintout_GetPaperRectPixels 2959
+#define wxPrintout_GetPPIPrinter 2960
+#define wxPrintout_GetPPIScreen 2961
+#define wxPrintout_GetTitle 2962
+#define wxPrintout_IsPreview 2963
+#define wxPrintout_FitThisSizeToPaper 2964
+#define wxPrintout_FitThisSizeToPage 2965
+#define wxPrintout_FitThisSizeToPageMargins 2966
+#define wxPrintout_MapScreenSizeToPaper 2967
+#define wxPrintout_MapScreenSizeToPage 2968
+#define wxPrintout_MapScreenSizeToPageMargins 2969
+#define wxPrintout_MapScreenSizeToDevice 2970
+#define wxPrintout_GetLogicalPaperRect 2971
+#define wxPrintout_GetLogicalPageRect 2972
+#define wxPrintout_GetLogicalPageMarginsRect 2973
+#define wxPrintout_SetLogicalOrigin 2974
+#define wxPrintout_OffsetLogicalOrigin 2975
+#define wxStyledTextCtrl_new_2 2976
+#define wxStyledTextCtrl_new_0 2977
+#define wxStyledTextCtrl_destruct 2978
+#define wxStyledTextCtrl_Create 2979
+#define wxStyledTextCtrl_AddText 2980
+#define wxStyledTextCtrl_AddStyledText 2981
+#define wxStyledTextCtrl_InsertText 2982
+#define wxStyledTextCtrl_ClearAll 2983
+#define wxStyledTextCtrl_ClearDocumentStyle 2984
+#define wxStyledTextCtrl_GetLength 2985
+#define wxStyledTextCtrl_GetCharAt 2986
+#define wxStyledTextCtrl_GetCurrentPos 2987
+#define wxStyledTextCtrl_GetAnchor 2988
+#define wxStyledTextCtrl_GetStyleAt 2989
+#define wxStyledTextCtrl_Redo 2990
+#define wxStyledTextCtrl_SetUndoCollection 2991
+#define wxStyledTextCtrl_SelectAll 2992
+#define wxStyledTextCtrl_SetSavePoint 2993
+#define wxStyledTextCtrl_GetStyledText 2994
+#define wxStyledTextCtrl_CanRedo 2995
+#define wxStyledTextCtrl_MarkerLineFromHandle 2996
+#define wxStyledTextCtrl_MarkerDeleteHandle 2997
+#define wxStyledTextCtrl_GetUndoCollection 2998
+#define wxStyledTextCtrl_GetViewWhiteSpace 2999
+#define wxStyledTextCtrl_SetViewWhiteSpace 3000
+#define wxStyledTextCtrl_PositionFromPoint 3001
+#define wxStyledTextCtrl_PositionFromPointClose 3002
+#define wxStyledTextCtrl_GotoLine 3003
+#define wxStyledTextCtrl_GotoPos 3004
+#define wxStyledTextCtrl_SetAnchor 3005
+#define wxStyledTextCtrl_GetCurLine 3006
+#define wxStyledTextCtrl_GetEndStyled 3007
+#define wxStyledTextCtrl_ConvertEOLs 3008
+#define wxStyledTextCtrl_GetEOLMode 3009
+#define wxStyledTextCtrl_SetEOLMode 3010
+#define wxStyledTextCtrl_StartStyling 3011
+#define wxStyledTextCtrl_SetStyling 3012
+#define wxStyledTextCtrl_GetBufferedDraw 3013
+#define wxStyledTextCtrl_SetBufferedDraw 3014
+#define wxStyledTextCtrl_SetTabWidth 3015
+#define wxStyledTextCtrl_GetTabWidth 3016
+#define wxStyledTextCtrl_SetCodePage 3017
+#define wxStyledTextCtrl_MarkerDefine 3018
+#define wxStyledTextCtrl_MarkerSetForeground 3019
+#define wxStyledTextCtrl_MarkerSetBackground 3020
+#define wxStyledTextCtrl_MarkerAdd 3021
+#define wxStyledTextCtrl_MarkerDelete 3022
+#define wxStyledTextCtrl_MarkerDeleteAll 3023
+#define wxStyledTextCtrl_MarkerGet 3024
+#define wxStyledTextCtrl_MarkerNext 3025
+#define wxStyledTextCtrl_MarkerPrevious 3026
+#define wxStyledTextCtrl_MarkerDefineBitmap 3027
+#define wxStyledTextCtrl_MarkerAddSet 3028
+#define wxStyledTextCtrl_MarkerSetAlpha 3029
+#define wxStyledTextCtrl_SetMarginType 3030
+#define wxStyledTextCtrl_GetMarginType 3031
+#define wxStyledTextCtrl_SetMarginWidth 3032
+#define wxStyledTextCtrl_GetMarginWidth 3033
+#define wxStyledTextCtrl_SetMarginMask 3034
+#define wxStyledTextCtrl_GetMarginMask 3035
+#define wxStyledTextCtrl_SetMarginSensitive 3036
+#define wxStyledTextCtrl_GetMarginSensitive 3037
+#define wxStyledTextCtrl_StyleClearAll 3038
+#define wxStyledTextCtrl_StyleSetForeground 3039
+#define wxStyledTextCtrl_StyleSetBackground 3040
+#define wxStyledTextCtrl_StyleSetBold 3041
+#define wxStyledTextCtrl_StyleSetItalic 3042
+#define wxStyledTextCtrl_StyleSetSize 3043
+#define wxStyledTextCtrl_StyleSetFaceName 3044
+#define wxStyledTextCtrl_StyleSetEOLFilled 3045
+#define wxStyledTextCtrl_StyleResetDefault 3046
+#define wxStyledTextCtrl_StyleSetUnderline 3047
+#define wxStyledTextCtrl_StyleSetCase 3048
+#define wxStyledTextCtrl_StyleSetHotSpot 3049
+#define wxStyledTextCtrl_SetSelForeground 3050
+#define wxStyledTextCtrl_SetSelBackground 3051
+#define wxStyledTextCtrl_GetSelAlpha 3052
+#define wxStyledTextCtrl_SetSelAlpha 3053
+#define wxStyledTextCtrl_SetCaretForeground 3054
+#define wxStyledTextCtrl_CmdKeyAssign 3055
+#define wxStyledTextCtrl_CmdKeyClear 3056
+#define wxStyledTextCtrl_CmdKeyClearAll 3057
+#define wxStyledTextCtrl_SetStyleBytes 3058
+#define wxStyledTextCtrl_StyleSetVisible 3059
+#define wxStyledTextCtrl_GetCaretPeriod 3060
+#define wxStyledTextCtrl_SetCaretPeriod 3061
+#define wxStyledTextCtrl_SetWordChars 3062
+#define wxStyledTextCtrl_BeginUndoAction 3063
+#define wxStyledTextCtrl_EndUndoAction 3064
+#define wxStyledTextCtrl_IndicatorSetStyle 3065
+#define wxStyledTextCtrl_IndicatorGetStyle 3066
+#define wxStyledTextCtrl_IndicatorSetForeground 3067
+#define wxStyledTextCtrl_IndicatorGetForeground 3068
+#define wxStyledTextCtrl_SetWhitespaceForeground 3069
+#define wxStyledTextCtrl_SetWhitespaceBackground 3070
+#define wxStyledTextCtrl_GetStyleBits 3071
+#define wxStyledTextCtrl_SetLineState 3072
+#define wxStyledTextCtrl_GetLineState 3073
+#define wxStyledTextCtrl_GetMaxLineState 3074
+#define wxStyledTextCtrl_GetCaretLineVisible 3075
+#define wxStyledTextCtrl_SetCaretLineVisible 3076
+#define wxStyledTextCtrl_GetCaretLineBackground 3077
+#define wxStyledTextCtrl_SetCaretLineBackground 3078
+#define wxStyledTextCtrl_AutoCompShow 3079
+#define wxStyledTextCtrl_AutoCompCancel 3080
+#define wxStyledTextCtrl_AutoCompActive 3081
+#define wxStyledTextCtrl_AutoCompPosStart 3082
+#define wxStyledTextCtrl_AutoCompComplete 3083
+#define wxStyledTextCtrl_AutoCompStops 3084
+#define wxStyledTextCtrl_AutoCompSetSeparator 3085
+#define wxStyledTextCtrl_AutoCompGetSeparator 3086
+#define wxStyledTextCtrl_AutoCompSelect 3087
+#define wxStyledTextCtrl_AutoCompSetCancelAtStart 3088
+#define wxStyledTextCtrl_AutoCompGetCancelAtStart 3089
+#define wxStyledTextCtrl_AutoCompSetFillUps 3090
+#define wxStyledTextCtrl_AutoCompSetChooseSingle 3091
+#define wxStyledTextCtrl_AutoCompGetChooseSingle 3092
+#define wxStyledTextCtrl_AutoCompSetIgnoreCase 3093
+#define wxStyledTextCtrl_AutoCompGetIgnoreCase 3094
+#define wxStyledTextCtrl_UserListShow 3095
+#define wxStyledTextCtrl_AutoCompSetAutoHide 3096
+#define wxStyledTextCtrl_AutoCompGetAutoHide 3097
+#define wxStyledTextCtrl_AutoCompSetDropRestOfWord 3098
+#define wxStyledTextCtrl_AutoCompGetDropRestOfWord 3099
+#define wxStyledTextCtrl_RegisterImage 3100
+#define wxStyledTextCtrl_ClearRegisteredImages 3101
+#define wxStyledTextCtrl_AutoCompGetTypeSeparator 3102
+#define wxStyledTextCtrl_AutoCompSetTypeSeparator 3103
+#define wxStyledTextCtrl_AutoCompSetMaxWidth 3104
+#define wxStyledTextCtrl_AutoCompGetMaxWidth 3105
+#define wxStyledTextCtrl_AutoCompSetMaxHeight 3106
+#define wxStyledTextCtrl_AutoCompGetMaxHeight 3107
+#define wxStyledTextCtrl_SetIndent 3108
+#define wxStyledTextCtrl_GetIndent 3109
+#define wxStyledTextCtrl_SetUseTabs 3110
+#define wxStyledTextCtrl_GetUseTabs 3111
+#define wxStyledTextCtrl_SetLineIndentation 3112
+#define wxStyledTextCtrl_GetLineIndentation 3113
+#define wxStyledTextCtrl_GetLineIndentPosition 3114
+#define wxStyledTextCtrl_GetColumn 3115
+#define wxStyledTextCtrl_SetUseHorizontalScrollBar 3116
+#define wxStyledTextCtrl_GetUseHorizontalScrollBar 3117
+#define wxStyledTextCtrl_SetIndentationGuides 3118
+#define wxStyledTextCtrl_GetIndentationGuides 3119
+#define wxStyledTextCtrl_SetHighlightGuide 3120
+#define wxStyledTextCtrl_GetHighlightGuide 3121
+#define wxStyledTextCtrl_GetLineEndPosition 3122
+#define wxStyledTextCtrl_GetCodePage 3123
+#define wxStyledTextCtrl_GetCaretForeground 3124
+#define wxStyledTextCtrl_GetReadOnly 3125
+#define wxStyledTextCtrl_SetCurrentPos 3126
+#define wxStyledTextCtrl_SetSelectionStart 3127
+#define wxStyledTextCtrl_GetSelectionStart 3128
+#define wxStyledTextCtrl_SetSelectionEnd 3129
+#define wxStyledTextCtrl_GetSelectionEnd 3130
+#define wxStyledTextCtrl_SetPrintMagnification 3131
+#define wxStyledTextCtrl_GetPrintMagnification 3132
+#define wxStyledTextCtrl_SetPrintColourMode 3133
+#define wxStyledTextCtrl_GetPrintColourMode 3134
+#define wxStyledTextCtrl_FindText 3135
+#define wxStyledTextCtrl_FormatRange 3136
+#define wxStyledTextCtrl_GetFirstVisibleLine 3137
+#define wxStyledTextCtrl_GetLine 3138
+#define wxStyledTextCtrl_GetLineCount 3139
+#define wxStyledTextCtrl_SetMarginLeft 3140
+#define wxStyledTextCtrl_GetMarginLeft 3141
+#define wxStyledTextCtrl_SetMarginRight 3142
+#define wxStyledTextCtrl_GetMarginRight 3143
+#define wxStyledTextCtrl_GetModify 3144
+#define wxStyledTextCtrl_SetSelection 3145
+#define wxStyledTextCtrl_GetSelectedText 3146
+#define wxStyledTextCtrl_GetTextRange 3147
+#define wxStyledTextCtrl_HideSelection 3148
+#define wxStyledTextCtrl_LineFromPosition 3149
+#define wxStyledTextCtrl_PositionFromLine 3150
+#define wxStyledTextCtrl_LineScroll 3151
+#define wxStyledTextCtrl_EnsureCaretVisible 3152
+#define wxStyledTextCtrl_ReplaceSelection 3153
+#define wxStyledTextCtrl_SetReadOnly 3154
+#define wxStyledTextCtrl_CanPaste 3155
+#define wxStyledTextCtrl_CanUndo 3156
+#define wxStyledTextCtrl_EmptyUndoBuffer 3157
+#define wxStyledTextCtrl_Undo 3158
+#define wxStyledTextCtrl_Cut 3159
+#define wxStyledTextCtrl_Copy 3160
+#define wxStyledTextCtrl_Paste 3161
+#define wxStyledTextCtrl_Clear 3162
+#define wxStyledTextCtrl_SetText 3163
+#define wxStyledTextCtrl_GetText 3164
+#define wxStyledTextCtrl_GetTextLength 3165
+#define wxStyledTextCtrl_GetOvertype 3166
+#define wxStyledTextCtrl_SetCaretWidth 3167
+#define wxStyledTextCtrl_GetCaretWidth 3168
+#define wxStyledTextCtrl_SetTargetStart 3169
+#define wxStyledTextCtrl_GetTargetStart 3170
+#define wxStyledTextCtrl_SetTargetEnd 3171
+#define wxStyledTextCtrl_GetTargetEnd 3172
+#define wxStyledTextCtrl_ReplaceTarget 3173
+#define wxStyledTextCtrl_SearchInTarget 3174
+#define wxStyledTextCtrl_SetSearchFlags 3175
+#define wxStyledTextCtrl_GetSearchFlags 3176
+#define wxStyledTextCtrl_CallTipShow 3177
+#define wxStyledTextCtrl_CallTipCancel 3178
+#define wxStyledTextCtrl_CallTipActive 3179
+#define wxStyledTextCtrl_CallTipPosAtStart 3180
+#define wxStyledTextCtrl_CallTipSetHighlight 3181
+#define wxStyledTextCtrl_CallTipSetBackground 3182
+#define wxStyledTextCtrl_CallTipSetForeground 3183
+#define wxStyledTextCtrl_CallTipSetForegroundHighlight 3184
+#define wxStyledTextCtrl_CallTipUseStyle 3185
+#define wxStyledTextCtrl_VisibleFromDocLine 3186
+#define wxStyledTextCtrl_DocLineFromVisible 3187
+#define wxStyledTextCtrl_WrapCount 3188
+#define wxStyledTextCtrl_SetFoldLevel 3189
+#define wxStyledTextCtrl_GetFoldLevel 3190
+#define wxStyledTextCtrl_GetLastChild 3191
+#define wxStyledTextCtrl_GetFoldParent 3192
+#define wxStyledTextCtrl_ShowLines 3193
+#define wxStyledTextCtrl_HideLines 3194
+#define wxStyledTextCtrl_GetLineVisible 3195
+#define wxStyledTextCtrl_SetFoldExpanded 3196
+#define wxStyledTextCtrl_GetFoldExpanded 3197
+#define wxStyledTextCtrl_ToggleFold 3198
+#define wxStyledTextCtrl_EnsureVisible 3199
+#define wxStyledTextCtrl_SetFoldFlags 3200
+#define wxStyledTextCtrl_EnsureVisibleEnforcePolicy 3201
+#define wxStyledTextCtrl_SetTabIndents 3202
+#define wxStyledTextCtrl_GetTabIndents 3203
+#define wxStyledTextCtrl_SetBackSpaceUnIndents 3204
+#define wxStyledTextCtrl_GetBackSpaceUnIndents 3205
+#define wxStyledTextCtrl_SetMouseDwellTime 3206
+#define wxStyledTextCtrl_GetMouseDwellTime 3207
+#define wxStyledTextCtrl_WordStartPosition 3208
+#define wxStyledTextCtrl_WordEndPosition 3209
+#define wxStyledTextCtrl_SetWrapMode 3210
+#define wxStyledTextCtrl_GetWrapMode 3211
+#define wxStyledTextCtrl_SetWrapVisualFlags 3212
+#define wxStyledTextCtrl_GetWrapVisualFlags 3213
+#define wxStyledTextCtrl_SetWrapVisualFlagsLocation 3214
+#define wxStyledTextCtrl_GetWrapVisualFlagsLocation 3215
+#define wxStyledTextCtrl_SetWrapStartIndent 3216
+#define wxStyledTextCtrl_GetWrapStartIndent 3217
+#define wxStyledTextCtrl_SetLayoutCache 3218
+#define wxStyledTextCtrl_GetLayoutCache 3219
+#define wxStyledTextCtrl_SetScrollWidth 3220
+#define wxStyledTextCtrl_GetScrollWidth 3221
+#define wxStyledTextCtrl_TextWidth 3222
+#define wxStyledTextCtrl_GetEndAtLastLine 3223
+#define wxStyledTextCtrl_TextHeight 3224
+#define wxStyledTextCtrl_SetUseVerticalScrollBar 3225
+#define wxStyledTextCtrl_GetUseVerticalScrollBar 3226
+#define wxStyledTextCtrl_AppendText 3227
+#define wxStyledTextCtrl_GetTwoPhaseDraw 3228
+#define wxStyledTextCtrl_SetTwoPhaseDraw 3229
+#define wxStyledTextCtrl_TargetFromSelection 3230
+#define wxStyledTextCtrl_LinesJoin 3231
+#define wxStyledTextCtrl_LinesSplit 3232
+#define wxStyledTextCtrl_SetFoldMarginColour 3233
+#define wxStyledTextCtrl_SetFoldMarginHiColour 3234
+#define wxStyledTextCtrl_LineDown 3235
+#define wxStyledTextCtrl_LineDownExtend 3236
+#define wxStyledTextCtrl_LineUp 3237
+#define wxStyledTextCtrl_LineUpExtend 3238
+#define wxStyledTextCtrl_CharLeft 3239
+#define wxStyledTextCtrl_CharLeftExtend 3240
+#define wxStyledTextCtrl_CharRight 3241
+#define wxStyledTextCtrl_CharRightExtend 3242
+#define wxStyledTextCtrl_WordLeft 3243
+#define wxStyledTextCtrl_WordLeftExtend 3244
+#define wxStyledTextCtrl_WordRight 3245
+#define wxStyledTextCtrl_WordRightExtend 3246
+#define wxStyledTextCtrl_Home 3247
+#define wxStyledTextCtrl_HomeExtend 3248
+#define wxStyledTextCtrl_LineEnd 3249
+#define wxStyledTextCtrl_LineEndExtend 3250
+#define wxStyledTextCtrl_DocumentStart 3251
+#define wxStyledTextCtrl_DocumentStartExtend 3252
+#define wxStyledTextCtrl_DocumentEnd 3253
+#define wxStyledTextCtrl_DocumentEndExtend 3254
+#define wxStyledTextCtrl_PageUp 3255
+#define wxStyledTextCtrl_PageUpExtend 3256
+#define wxStyledTextCtrl_PageDown 3257
+#define wxStyledTextCtrl_PageDownExtend 3258
+#define wxStyledTextCtrl_EditToggleOvertype 3259
+#define wxStyledTextCtrl_Cancel 3260
+#define wxStyledTextCtrl_DeleteBack 3261
+#define wxStyledTextCtrl_Tab 3262
+#define wxStyledTextCtrl_BackTab 3263
+#define wxStyledTextCtrl_NewLine 3264
+#define wxStyledTextCtrl_FormFeed 3265
+#define wxStyledTextCtrl_VCHome 3266
+#define wxStyledTextCtrl_VCHomeExtend 3267
+#define wxStyledTextCtrl_ZoomIn 3268
+#define wxStyledTextCtrl_ZoomOut 3269
+#define wxStyledTextCtrl_DelWordLeft 3270
+#define wxStyledTextCtrl_DelWordRight 3271
+#define wxStyledTextCtrl_LineCut 3272
+#define wxStyledTextCtrl_LineDelete 3273
+#define wxStyledTextCtrl_LineTranspose 3274
+#define wxStyledTextCtrl_LineDuplicate 3275
+#define wxStyledTextCtrl_LowerCase 3276
+#define wxStyledTextCtrl_UpperCase 3277
+#define wxStyledTextCtrl_LineScrollDown 3278
+#define wxStyledTextCtrl_LineScrollUp 3279
+#define wxStyledTextCtrl_DeleteBackNotLine 3280
+#define wxStyledTextCtrl_HomeDisplay 3281
+#define wxStyledTextCtrl_HomeDisplayExtend 3282
+#define wxStyledTextCtrl_LineEndDisplay 3283
+#define wxStyledTextCtrl_LineEndDisplayExtend 3284
+#define wxStyledTextCtrl_HomeWrapExtend 3285
+#define wxStyledTextCtrl_LineEndWrap 3286
+#define wxStyledTextCtrl_LineEndWrapExtend 3287
+#define wxStyledTextCtrl_VCHomeWrap 3288
+#define wxStyledTextCtrl_VCHomeWrapExtend 3289
+#define wxStyledTextCtrl_LineCopy 3290
+#define wxStyledTextCtrl_MoveCaretInsideView 3291
+#define wxStyledTextCtrl_LineLength 3292
+#define wxStyledTextCtrl_BraceHighlight 3293
+#define wxStyledTextCtrl_BraceBadLight 3294
+#define wxStyledTextCtrl_BraceMatch 3295
+#define wxStyledTextCtrl_GetViewEOL 3296
+#define wxStyledTextCtrl_SetViewEOL 3297
+#define wxStyledTextCtrl_SetModEventMask 3298
+#define wxStyledTextCtrl_GetEdgeColumn 3299
+#define wxStyledTextCtrl_SetEdgeColumn 3300
+#define wxStyledTextCtrl_SetEdgeMode 3301
+#define wxStyledTextCtrl_GetEdgeMode 3302
+#define wxStyledTextCtrl_GetEdgeColour 3303
+#define wxStyledTextCtrl_SetEdgeColour 3304
+#define wxStyledTextCtrl_SearchAnchor 3305
+#define wxStyledTextCtrl_SearchNext 3306
+#define wxStyledTextCtrl_SearchPrev 3307
+#define wxStyledTextCtrl_LinesOnScreen 3308
+#define wxStyledTextCtrl_UsePopUp 3309
+#define wxStyledTextCtrl_SelectionIsRectangle 3310
+#define wxStyledTextCtrl_SetZoom 3311
+#define wxStyledTextCtrl_GetZoom 3312
+#define wxStyledTextCtrl_GetModEventMask 3313
+#define wxStyledTextCtrl_SetSTCFocus 3314
+#define wxStyledTextCtrl_GetSTCFocus 3315
+#define wxStyledTextCtrl_SetStatus 3316
+#define wxStyledTextCtrl_GetStatus 3317
+#define wxStyledTextCtrl_SetMouseDownCaptures 3318
+#define wxStyledTextCtrl_GetMouseDownCaptures 3319
+#define wxStyledTextCtrl_SetSTCCursor 3320
+#define wxStyledTextCtrl_GetSTCCursor 3321
+#define wxStyledTextCtrl_SetControlCharSymbol 3322
+#define wxStyledTextCtrl_GetControlCharSymbol 3323
+#define wxStyledTextCtrl_WordPartLeft 3324
+#define wxStyledTextCtrl_WordPartLeftExtend 3325
+#define wxStyledTextCtrl_WordPartRight 3326
+#define wxStyledTextCtrl_WordPartRightExtend 3327
+#define wxStyledTextCtrl_SetVisiblePolicy 3328
+#define wxStyledTextCtrl_DelLineLeft 3329
+#define wxStyledTextCtrl_DelLineRight 3330
+#define wxStyledTextCtrl_GetXOffset 3331
+#define wxStyledTextCtrl_ChooseCaretX 3332
+#define wxStyledTextCtrl_SetXCaretPolicy 3333
+#define wxStyledTextCtrl_SetYCaretPolicy 3334
+#define wxStyledTextCtrl_GetPrintWrapMode 3335
+#define wxStyledTextCtrl_SetHotspotActiveForeground 3336
+#define wxStyledTextCtrl_SetHotspotActiveBackground 3337
+#define wxStyledTextCtrl_SetHotspotActiveUnderline 3338
+#define wxStyledTextCtrl_SetHotspotSingleLine 3339
+#define wxStyledTextCtrl_ParaDownExtend 3340
+#define wxStyledTextCtrl_ParaUp 3341
+#define wxStyledTextCtrl_ParaUpExtend 3342
+#define wxStyledTextCtrl_PositionBefore 3343
+#define wxStyledTextCtrl_PositionAfter 3344
+#define wxStyledTextCtrl_CopyRange 3345
+#define wxStyledTextCtrl_CopyText 3346
+#define wxStyledTextCtrl_SetSelectionMode 3347
+#define wxStyledTextCtrl_GetSelectionMode 3348
+#define wxStyledTextCtrl_LineDownRectExtend 3349
+#define wxStyledTextCtrl_LineUpRectExtend 3350
+#define wxStyledTextCtrl_CharLeftRectExtend 3351
+#define wxStyledTextCtrl_CharRightRectExtend 3352
+#define wxStyledTextCtrl_HomeRectExtend 3353
+#define wxStyledTextCtrl_VCHomeRectExtend 3354
+#define wxStyledTextCtrl_LineEndRectExtend 3355
+#define wxStyledTextCtrl_PageUpRectExtend 3356
+#define wxStyledTextCtrl_PageDownRectExtend 3357
+#define wxStyledTextCtrl_StutteredPageUp 3358
+#define wxStyledTextCtrl_StutteredPageUpExtend 3359
+#define wxStyledTextCtrl_StutteredPageDown 3360
+#define wxStyledTextCtrl_StutteredPageDownExtend 3361
+#define wxStyledTextCtrl_WordLeftEnd 3362
+#define wxStyledTextCtrl_WordLeftEndExtend 3363
+#define wxStyledTextCtrl_WordRightEnd 3364
+#define wxStyledTextCtrl_WordRightEndExtend 3365
+#define wxStyledTextCtrl_SetWhitespaceChars 3366
+#define wxStyledTextCtrl_SetCharsDefault 3367
+#define wxStyledTextCtrl_AutoCompGetCurrent 3368
+#define wxStyledTextCtrl_Allocate 3369
+#define wxStyledTextCtrl_FindColumn 3370
+#define wxStyledTextCtrl_GetCaretSticky 3371
+#define wxStyledTextCtrl_SetCaretSticky 3372
+#define wxStyledTextCtrl_ToggleCaretSticky 3373
+#define wxStyledTextCtrl_SetPasteConvertEndings 3374
+#define wxStyledTextCtrl_GetPasteConvertEndings 3375
+#define wxStyledTextCtrl_SelectionDuplicate 3376
+#define wxStyledTextCtrl_SetCaretLineBackAlpha 3377
+#define wxStyledTextCtrl_GetCaretLineBackAlpha 3378
+#define wxStyledTextCtrl_StartRecord 3379
+#define wxStyledTextCtrl_StopRecord 3380
+#define wxStyledTextCtrl_SetLexer 3381
+#define wxStyledTextCtrl_GetLexer 3382
+#define wxStyledTextCtrl_Colourise 3383
+#define wxStyledTextCtrl_SetProperty 3384
+#define wxStyledTextCtrl_SetKeyWords 3385
+#define wxStyledTextCtrl_SetLexerLanguage 3386
+#define wxStyledTextCtrl_GetProperty 3387
+#define wxStyledTextCtrl_GetStyleBitsNeeded 3388
+#define wxStyledTextCtrl_GetCurrentLine 3389
+#define wxStyledTextCtrl_StyleSetSpec 3390
+#define wxStyledTextCtrl_StyleSetFont 3391
+#define wxStyledTextCtrl_StyleSetFontAttr 3392
+#define wxStyledTextCtrl_StyleSetCharacterSet 3393
+#define wxStyledTextCtrl_StyleSetFontEncoding 3394
+#define wxStyledTextCtrl_CmdKeyExecute 3395
+#define wxStyledTextCtrl_SetMargins 3396
+#define wxStyledTextCtrl_GetSelection 3397
+#define wxStyledTextCtrl_PointFromPosition 3398
+#define wxStyledTextCtrl_ScrollToLine 3399
+#define wxStyledTextCtrl_ScrollToColumn 3400
+#define wxStyledTextCtrl_SetVScrollBar 3401
+#define wxStyledTextCtrl_SetHScrollBar 3402
+#define wxStyledTextCtrl_GetLastKeydownProcessed 3403
+#define wxStyledTextCtrl_SetLastKeydownProcessed 3404
+#define wxStyledTextCtrl_SaveFile 3405
+#define wxStyledTextCtrl_LoadFile 3406
+#define wxStyledTextCtrl_DoDragOver 3407
+#define wxStyledTextCtrl_DoDropText 3408
+#define wxStyledTextCtrl_GetUseAntiAliasing 3409
+#define wxStyledTextCtrl_AddTextRaw 3410
+#define wxStyledTextCtrl_InsertTextRaw 3411
+#define wxStyledTextCtrl_GetCurLineRaw 3412
+#define wxStyledTextCtrl_GetLineRaw 3413
+#define wxStyledTextCtrl_GetSelectedTextRaw 3414
+#define wxStyledTextCtrl_GetTextRangeRaw 3415
+#define wxStyledTextCtrl_SetTextRaw 3416
+#define wxStyledTextCtrl_GetTextRaw 3417
+#define wxStyledTextCtrl_AppendTextRaw 3418
+#define wxArtProvider_GetBitmap 3419
+#define wxArtProvider_GetIcon 3420
+#define wxTreeEvent_GetKeyCode 3421
+#define wxTreeEvent_GetItem 3422
+#define wxTreeEvent_GetKeyEvent 3423
+#define wxTreeEvent_GetLabel 3424
+#define wxTreeEvent_GetOldItem 3425
+#define wxTreeEvent_GetPoint 3426
+#define wxTreeEvent_IsEditCancelled 3427
+#define wxTreeEvent_SetToolTip 3428
+#define wxNotebookEvent_GetOldSelection 3429
+#define wxNotebookEvent_GetSelection 3430
+#define wxNotebookEvent_SetOldSelection 3431
+#define wxNotebookEvent_SetSelection 3432
+#define wxFileDataObject_new 3433
+#define wxFileDataObject_AddFile 3434
+#define wxFileDataObject_GetFilenames 3435
+#define wxFileDataObject_destroy 3436
+#define wxTextDataObject_new 3437
+#define wxTextDataObject_GetTextLength 3438
+#define wxTextDataObject_GetText 3439
+#define wxTextDataObject_SetText 3440
+#define wxTextDataObject_destroy 3441
+#define wxBitmapDataObject_new_1_1 3442
+#define wxBitmapDataObject_new_1_0 3443
+#define wxBitmapDataObject_GetBitmap 3444
+#define wxBitmapDataObject_SetBitmap 3445
+#define wxBitmapDataObject_destroy 3446
+#define wxClipboard_new 3448
+#define wxClipboard_destruct 3449
+#define wxClipboard_AddData 3450
+#define wxClipboard_Clear 3451
+#define wxClipboard_Close 3452
+#define wxClipboard_Flush 3453
+#define wxClipboard_GetData 3454
+#define wxClipboard_IsOpened 3455
+#define wxClipboard_Open 3456
+#define wxClipboard_SetData 3457
+#define wxClipboard_UsePrimarySelection 3459
+#define wxClipboard_IsSupported 3460
+#define wxClipboard_Get 3461
+#define wxSpinEvent_GetPosition 3462
+#define wxSpinEvent_SetPosition 3463
+#define wxSplitterWindow_new_0 3464
+#define wxSplitterWindow_new_2 3465
+#define wxSplitterWindow_destruct 3466
+#define wxSplitterWindow_Create 3467
+#define wxSplitterWindow_GetMinimumPaneSize 3468
+#define wxSplitterWindow_GetSashGravity 3469
+#define wxSplitterWindow_GetSashPosition 3470
+#define wxSplitterWindow_GetSplitMode 3471
+#define wxSplitterWindow_GetWindow1 3472
+#define wxSplitterWindow_GetWindow2 3473
+#define wxSplitterWindow_Initialize 3474
+#define wxSplitterWindow_IsSplit 3475
+#define wxSplitterWindow_ReplaceWindow 3476
+#define wxSplitterWindow_SetSashGravity 3477
+#define wxSplitterWindow_SetSashPosition 3478
+#define wxSplitterWindow_SetSashSize 3479
+#define wxSplitterWindow_SetMinimumPaneSize 3480
+#define wxSplitterWindow_SetSplitMode 3481
+#define wxSplitterWindow_SplitHorizontally 3482
+#define wxSplitterWindow_SplitVertically 3483
+#define wxSplitterWindow_Unsplit 3484
+#define wxSplitterWindow_UpdateSize 3485
+#define wxSplitterEvent_GetSashPosition 3486
+#define wxSplitterEvent_GetX 3487
+#define wxSplitterEvent_GetY 3488
+#define wxSplitterEvent_GetWindowBeingRemoved 3489
+#define wxSplitterEvent_SetSashPosition 3490
+#define wxHtmlWindow_new_0 3491
+#define wxHtmlWindow_new_2 3492
+#define wxHtmlWindow_AppendToPage 3493
+#define wxHtmlWindow_GetOpenedAnchor 3494
+#define wxHtmlWindow_GetOpenedPage 3495
+#define wxHtmlWindow_GetOpenedPageTitle 3496
+#define wxHtmlWindow_GetRelatedFrame 3497
+#define wxHtmlWindow_HistoryBack 3498
+#define wxHtmlWindow_HistoryCanBack 3499
+#define wxHtmlWindow_HistoryCanForward 3500
+#define wxHtmlWindow_HistoryClear 3501
+#define wxHtmlWindow_HistoryForward 3502
+#define wxHtmlWindow_LoadFile 3503
+#define wxHtmlWindow_LoadPage 3504
+#define wxHtmlWindow_SelectAll 3505
+#define wxHtmlWindow_SelectionToText 3506
+#define wxHtmlWindow_SelectLine 3507
+#define wxHtmlWindow_SelectWord 3508
+#define wxHtmlWindow_SetBorders 3509
+#define wxHtmlWindow_SetFonts 3510
+#define wxHtmlWindow_SetPage 3511
+#define wxHtmlWindow_SetRelatedFrame 3512
+#define wxHtmlWindow_SetRelatedStatusBar 3513
+#define wxHtmlWindow_ToText 3514
+#define wxHtmlWindow_destroy 3515
+#define wxHtmlLinkEvent_GetLinkInfo 3516
+#define wxSystemSettings_GetColour 3517
+#define wxSystemSettings_GetFont 3518
+#define wxSystemSettings_GetMetric 3519
+#define wxSystemSettings_GetScreenType 3520
+#define wxSystemOptions_GetOption 3521
+#define wxSystemOptions_GetOptionInt 3522
+#define wxSystemOptions_HasOption 3523
+#define wxSystemOptions_IsFalse 3524
+#define wxSystemOptions_SetOption_2_1 3525
+#define wxSystemOptions_SetOption_2_0 3526
+#define wxAuiNotebookEvent_SetSelection 3527
+#define wxAuiNotebookEvent_GetSelection 3528
+#define wxAuiNotebookEvent_SetOldSelection 3529
+#define wxAuiNotebookEvent_GetOldSelection 3530
+#define wxAuiNotebookEvent_SetDragSource 3531
+#define wxAuiNotebookEvent_GetDragSource 3532
+#define wxAuiManagerEvent_SetManager 3533
+#define wxAuiManagerEvent_GetManager 3534
+#define wxAuiManagerEvent_SetPane 3535
+#define wxAuiManagerEvent_GetPane 3536
+#define wxAuiManagerEvent_SetButton 3537
+#define wxAuiManagerEvent_GetButton 3538
+#define wxAuiManagerEvent_SetDC 3539
+#define wxAuiManagerEvent_GetDC 3540
+#define wxAuiManagerEvent_Veto 3541
+#define wxAuiManagerEvent_GetVeto 3542
+#define wxAuiManagerEvent_SetCanVeto 3543
+#define wxAuiManagerEvent_CanVeto 3544
+#define wxLogNull_new 3545
+#define wxLogNull_destroy 3546
+#define wxTaskBarIcon_new 3547
+#define wxTaskBarIcon_destruct 3548
+#define wxTaskBarIcon_PopupMenu 3549
+#define wxTaskBarIcon_RemoveIcon 3550
+#define wxTaskBarIcon_SetIcon 3551
+#define wxLocale_new_0 3552
+#define wxLocale_new_2 3554
+#define wxLocale_destruct 3555
+#define wxLocale_Init 3557
+#define wxLocale_AddCatalog_1 3558
+#define wxLocale_AddCatalog_3 3559
+#define wxLocale_AddCatalogLookupPathPrefix 3560
+#define wxLocale_GetCanonicalName 3561
+#define wxLocale_GetLanguage 3562
+#define wxLocale_GetLanguageName 3563
+#define wxLocale_GetLocale 3564
+#define wxLocale_GetName 3565
+#define wxLocale_GetString_2 3566
+#define wxLocale_GetString_4 3567
+#define wxLocale_GetHeaderValue 3568
+#define wxLocale_GetSysName 3569
+#define wxLocale_GetSystemEncoding 3570
+#define wxLocale_GetSystemEncodingName 3571
+#define wxLocale_GetSystemLanguage 3572
+#define wxLocale_IsLoaded 3573
+#define wxLocale_IsOk 3574
+#define wxActivateEvent_GetActive 3575
+#define wxPopupWindow_new_2 3577
+#define wxPopupWindow_new_0 3578
+#define wxPopupWindow_destruct 3580
+#define wxPopupWindow_Create 3581
+#define wxPopupWindow_Position 3582
+#define wxPopupTransientWindow_new_0 3583
+#define wxPopupTransientWindow_new_2 3584
+#define wxPopupTransientWindow_destruct 3585
+#define wxPopupTransientWindow_Popup 3586
+#define wxPopupTransientWindow_Dismiss 3587
+#define wxOverlay_new 3588
+#define wxOverlay_destruct 3589
+#define wxOverlay_Reset 3590
+#define wxDCOverlay_new_6 3591
+#define wxDCOverlay_new_2 3592
+#define wxDCOverlay_destruct 3593
+#define wxDCOverlay_Clear 3594
diff --git a/lib/wx/c_src/wxe_helpers.cpp b/lib/wx/c_src/wxe_helpers.cpp
index cc57374d5b..1696b8bd50 100644
--- a/lib/wx/c_src/wxe_helpers.cpp
+++ b/lib/wx/c_src/wxe_helpers.cpp
@@ -61,6 +61,7 @@ wxeFifo::wxeFifo(unsigned int sz)
m_max = sz;
m_n = 0;
m_first = 0;
+ cb_start = 0;
m_old = NULL;
for(unsigned int i = 0; i < sz; i++) {
m_q[i].buffer = NULL;
@@ -76,15 +77,30 @@ wxeFifo::~wxeFifo() {
wxeCommand * wxeFifo::Get()
{
unsigned int pos;
- if(m_n > 0) {
+ do {
+ if(m_n <= 0)
+ return NULL;
+
pos = m_first++;
m_n--;
m_first %= m_max;
- return &m_q[pos];
- }
- return NULL;
+ } while(m_q[pos].op == -1);
+ return &m_q[pos];
+}
+
+wxeCommand * wxeFifo::Peek(unsigned int *i)
+{
+ unsigned int pos;
+ do {
+ if(*i >= m_n || m_n <= 0)
+ return NULL;
+ pos = (m_first+*i) % m_max;
+ (*i)++;
+ } while(m_q[pos].op == -1);
+ return &m_q[pos];
}
+
void wxeFifo::Add(int fc, char * cbuf,int buflen, wxe_data *sd)
{
unsigned int pos;
@@ -140,10 +156,12 @@ void wxeFifo::Append(wxeCommand *orig)
pos = (m_first + m_n) % m_max;
m_n++;
+
curr = &m_q[pos];
+ curr->op = orig->op;
+ if(curr->op == -1) return;
curr->caller = orig->caller;
curr->port = orig->port;
- curr->op = orig->op;
curr->len = orig->len;
curr->bin[0] = orig->bin[0];
curr->bin[1] = orig->bin[1];
@@ -171,17 +189,19 @@ void wxeFifo::Realloc()
wxeCommand * old = m_q;
wxeCommand * queue = (wxeCommand *)driver_alloc(new_sz*sizeof(wxeCommand));
+ // fprintf(stderr, "\r\nrealloc qsz %d\r\n", new_sz);fflush(stderr);
+
m_max=new_sz;
m_first = 0;
m_n=0;
m_q = queue;
for(i=0; i < n; i++) {
- unsigned int pos = i+first;
- if(old[pos%max].op >= 0) {
- Append(&old[pos%max]);
- }
+ unsigned int pos = (i+first)%max;
+ if(old[pos].op >= 0)
+ Append(&old[pos]);
}
+
for(i = m_n; i < new_sz; i++) { // Reset the rest
m_q[i].buffer = NULL;
m_q[i].op = -1;
@@ -190,6 +210,26 @@ void wxeFifo::Realloc()
m_old = old;
}
+// Strip end of queue if ops are already taken care of, avoids reallocs
+void wxeFifo::Strip()
+{
+ while((m_n > 0) && (m_q[(m_first + m_n - 1)%m_max].op == -1)) {
+ m_n--;
+ }
+}
+
+unsigned int wxeFifo::Cleanup(unsigned int def)
+{
+ if(m_old) {
+ driver_free(m_old);
+ m_old = NULL;
+ // Realloced we need to start from the beginning
+ return 0;
+ } else {
+ return def;
+ }
+}
+
/* ****************************************************************************
* TreeItemData
* ****************************************************************************/
diff --git a/lib/wx/c_src/wxe_helpers.h b/lib/wx/c_src/wxe_helpers.h
index 4f9d9ca9c3..ff949e332b 100644
--- a/lib/wx/c_src/wxe_helpers.h
+++ b/lib/wx/c_src/wxe_helpers.h
@@ -67,9 +67,13 @@ class wxeFifo {
void Append(wxeCommand *Other);
wxeCommand * Get();
+ wxeCommand * Peek(unsigned int *item);
void Realloc();
+ void Strip();
+ unsigned int Cleanup(unsigned int peek=0);
+ unsigned int cb_start;
unsigned int m_max;
unsigned int m_first;
unsigned int m_n;
diff --git a/lib/wx/c_src/wxe_impl.cpp b/lib/wx/c_src/wxe_impl.cpp
index 5b34f08704..f81d0bbbd9 100644
--- a/lib/wx/c_src/wxe_impl.cpp
+++ b/lib/wx/c_src/wxe_impl.cpp
@@ -57,10 +57,8 @@ extern ErlDrvTermData init_caller;
extern int wxe_status;
wxeFifo * wxe_queue = NULL;
-wxeFifo * wxe_queue_cb_saved = NULL;
unsigned int wxe_needs_signal = 0; // inside batch if larger than 0
-unsigned int wxe_cb_invoked = 0;
/* ************************************************************
* Commands from erlang
@@ -123,11 +121,10 @@ bool WxeApp::OnInit()
{
global_me = new wxeMemEnv();
- wxe_queue = new wxeFifo(1000);
- wxe_queue_cb_saved = new wxeFifo(200);
+ wxe_queue = new wxeFifo(2000);
cb_buff = NULL;
recurse_level = 0;
- delayed_delete = new wxeFifo(10);
+ delayed_delete = new wxeFifo(100);
delayed_cleanup = new wxList;
wxe_ps_init2();
@@ -173,7 +170,6 @@ void WxeApp::shutdown(wxeMetaCommand& Ecmd) {
wxe_status = WXE_EXITING;
ExitMainLoop();
delete wxe_queue;
- delete wxe_queue_cb_saved;
}
void WxeApp::dummy_close(wxEvent& Ev) {
@@ -230,11 +226,10 @@ void handle_event_callback(ErlDrvPort port, ErlDrvTermData process)
// Should we be able to handle commands when recursing? probably
// fprintf(stderr, "\r\nCB EV Start %lu \r\n", process);fflush(stderr);
app->recurse_level++;
- app->dispatch_cb(wxe_queue, wxe_queue_cb_saved, process);
+ app->dispatch_cb(wxe_queue, process);
app->recurse_level--;
// fprintf(stderr, "CB EV done %lu \r\n", process);fflush(stderr);
driver_demonitor_process(port, &monitor);
- wxe_cb_invoked = 1;
}
}
@@ -242,16 +237,11 @@ void WxeApp::dispatch_cmds()
{
if(wxe_status != WXE_INITIATED)
return;
- do {
- wxe_cb_invoked = 0;
- recurse_level++;
- // fprintf(stderr, "\r\ndispatch_saved 0 \r\n");fflush(stderr);
- int level = dispatch(wxe_queue_cb_saved, 0, WXE_STORED);
- // fprintf(stderr, "\r\ndispatch_normal %d\r\n", level);fflush(stderr);
- dispatch(wxe_queue, level, WXE_NORMAL);
- // fprintf(stderr, "\r\ndispatch_done \r\n");fflush(stderr);
- recurse_level--;
- } while(wxe_cb_invoked);
+ recurse_level++;
+ // fprintf(stderr, "\r\ndispatch_normal %d\r\n", level);fflush(stderr);
+ dispatch(wxe_queue);
+ // fprintf(stderr, "\r\ndispatch_done \r\n");fflush(stderr);
+ recurse_level--;
// Cleanup old memenv's and deleted objects
if(recurse_level == 0) {
@@ -260,6 +250,7 @@ void WxeApp::dispatch_cmds()
wxe_dispatch(*curr);
curr->Delete();
}
+ delayed_delete->Cleanup();
if(delayed_cleanup->size() > 0)
for( wxList::compatibility_iterator node = delayed_cleanup->GetFirst();
node;
@@ -269,28 +260,19 @@ void WxeApp::dispatch_cmds()
destroyMemEnv(*event);
delete event;
}
- if(wxe_queue_cb_saved->m_old) {
- driver_free(wxe_queue_cb_saved->m_old);
- wxe_queue_cb_saved->m_old = NULL;
- }
- if(delayed_delete->m_old) {
- driver_free(delayed_delete->m_old);
- delayed_delete->m_old = NULL;
- }
}
}
-int WxeApp::dispatch(wxeFifo * batch, int blevel, int list_type)
+int WxeApp::dispatch(wxeFifo * batch)
{
int ping = 0;
+ int blevel = 0;
wxeCommand *event;
- if(list_type == WXE_NORMAL) erl_drv_mutex_lock(wxe_batch_locker_m);
+ erl_drv_mutex_lock(wxe_batch_locker_m);
while(true) {
while((event = batch->Get()) != NULL) {
- if(list_type == WXE_NORMAL) erl_drv_mutex_unlock(wxe_batch_locker_m);
+ erl_drv_mutex_unlock(wxe_batch_locker_m);
switch(event->op) {
- case -1:
- break;
case WXE_BATCH_END:
{--blevel; }
break;
@@ -321,20 +303,10 @@ int WxeApp::dispatch(wxeFifo * batch, int blevel, int list_type)
break;
}
event->Delete();
- if(list_type == WXE_NORMAL) {
- if(wxe_cb_invoked)
- return blevel;
- else
- erl_drv_mutex_lock(wxe_batch_locker_m);
- }
+ erl_drv_mutex_lock(wxe_batch_locker_m);
+ batch->Cleanup();
}
- if(list_type == WXE_STORED)
- return blevel;
- if(blevel <= 0) { // list_type == WXE_NORMAL
- if(wxe_queue->m_old) {
- driver_free(wxe_queue->m_old);
- wxe_queue->m_old = NULL;
- }
+ if(blevel <= 0) {
erl_drv_mutex_unlock(wxe_batch_locker_m);
return blevel;
}
@@ -348,12 +320,13 @@ int WxeApp::dispatch(wxeFifo * batch, int blevel, int list_type)
}
}
-void WxeApp::dispatch_cb(wxeFifo * batch, wxeFifo * temp, ErlDrvTermData process) {
+void WxeApp::dispatch_cb(wxeFifo * batch, ErlDrvTermData process) {
wxeCommand *event;
+ unsigned int peek;
erl_drv_mutex_lock(wxe_batch_locker_m);
+ peek = batch->Cleanup(batch->cb_start);
while(true) {
- while((event = batch->Get()) != NULL) {
- erl_drv_mutex_unlock(wxe_batch_locker_m);
+ while((event = batch->Peek(&peek)) != NULL) {
wxeMemEnv *memenv = getMemEnv(event->port);
// fprintf(stderr, " Ev %d %lu\r\n", event->op, event->caller);
if(event->caller == process || // Callbacks from CB process only
@@ -361,8 +334,8 @@ void WxeApp::dispatch_cb(wxeFifo * batch, wxeFifo * temp, ErlDrvTermData process
event->op == WXE_CB_DIED || // Event callback process died
// Allow connect_cb during CB i.e. msg from wxe_server.
(memenv && event->caller == memenv->owner)) {
+ erl_drv_mutex_unlock(wxe_batch_locker_m);
switch(event->op) {
- case -1:
case WXE_BATCH_END:
case WXE_BATCH_BEGIN:
case WXE_DEBUG_PING:
@@ -373,52 +346,42 @@ void WxeApp::dispatch_cb(wxeFifo * batch, wxeFifo * temp, ErlDrvTermData process
memcpy(cb_buff, event->buffer, event->len);
} // continue
case WXE_CB_DIED:
+ batch->cb_start = 0;
event->Delete();
+ erl_drv_mutex_lock(wxe_batch_locker_m);
+ batch->Strip();
+ erl_drv_mutex_unlock(wxe_batch_locker_m);
return;
case WXE_CB_START:
// CB start from now accept message from CB process only
process = event->caller;
break;
default:
- size_t start=temp->m_n;
+ batch->cb_start = peek; // In case of recursive callbacks
if(event->op < OPENGL_START) {
- // fprintf(stderr, " cb %d \r\n", event->op);
wxe_dispatch(*event);
} else {
gl_dispatch(event->op,event->buffer,event->caller,event->bin);
}
- if(temp->m_n > start) {
- erl_drv_mutex_lock(wxe_batch_locker_m);
- // We have recursed dispatch_cb and messages for this
- // callback may be saved on temp list move them
- // to orig list
- for(unsigned int i=start; i < temp->m_n; i++) {
- wxeCommand *ev = &temp->m_q[(temp->m_first+i) % temp->m_max];
- if(ev->caller == process) {
- batch->Append(ev);
- }
- }
- erl_drv_mutex_unlock(wxe_batch_locker_m);
- }
break;
}
event->Delete();
- } else {
- // fprintf(stderr, " save %d %lu\r\n", event->op, event->caller);
- temp->Append(event);
+ erl_drv_mutex_lock(wxe_batch_locker_m);
+ peek = batch->Cleanup(peek);
}
- erl_drv_mutex_lock(wxe_batch_locker_m);
}
// sleep until something happens
// fprintf(stderr, "%s:%d sleep %d %d\r\n", __FILE__, __LINE__,
- // batch->m_n, temp->m_n);fflush(stderr);
+ // peek, batch->m_n);fflush(stderr);
wxe_needs_signal = 1;
- while(batch->m_n == 0) {
+ while(peek >= batch->m_n) {
erl_drv_cond_wait(wxe_batch_locker_c, wxe_batch_locker_m);
+ peek = batch->Cleanup(peek);
}
wxe_needs_signal = 0;
}
}
+
/* Memory handling */
void WxeApp::newMemEnv(wxeMetaCommand& Ecmd) {
diff --git a/lib/wx/c_src/wxe_impl.h b/lib/wx/c_src/wxe_impl.h
index d6d3095a0f..fd25296c73 100644
--- a/lib/wx/c_src/wxe_impl.h
+++ b/lib/wx/c_src/wxe_impl.h
@@ -67,8 +67,8 @@ public:
void shutdown(wxeMetaCommand& event);
- int dispatch(wxeFifo *, int, int);
- void dispatch_cb(wxeFifo * batch, wxeFifo * temp, ErlDrvTermData process);
+ int dispatch(wxeFifo *);
+ void dispatch_cb(wxeFifo * batch, ErlDrvTermData process);
void wxe_dispatch(wxeCommand& event);
diff --git a/lib/wx/examples/demo/ex_canvas.erl b/lib/wx/examples/demo/ex_canvas.erl
index 1cbb96de1f..acc94743d6 100644
--- a/lib/wx/examples/demo/ex_canvas.erl
+++ b/lib/wx/examples/demo/ex_canvas.erl
@@ -35,7 +35,9 @@
parent,
config,
canvas,
- bitmap
+ bitmap,
+ overlay,
+ pos
}).
start(Config) ->
@@ -60,6 +62,10 @@ do_init(Config) ->
wxPanel:connect(Canvas, paint, [callback]),
wxPanel:connect(Canvas, size),
+ wxPanel:connect(Canvas, left_down),
+ wxPanel:connect(Canvas, left_up),
+ wxPanel:connect(Canvas, motion),
+
wxPanel:connect(Button, command_button_clicked),
%% Add to sizers
@@ -78,7 +84,9 @@ do_init(Config) ->
Bitmap = wxBitmap:new(erlang:max(W,30),erlang:max(30,H)),
{Panel, #state{parent=Panel, config=Config,
- canvas = Canvas, bitmap = Bitmap}}.
+ canvas = Canvas, bitmap = Bitmap,
+ overlay = wxOverlay:new()
+ }}.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Sync event from callback events, paint event must be handled in callbacks
@@ -127,11 +135,39 @@ handle_event(#wx{event = #wxCommand{type = command_button_clicked}},
wxBitmap:destroy(Bmp),
{noreply, State};
handle_event(#wx{event = #wxSize{size={W,H}}},
- State = #state{bitmap=Prev}) ->
+ State = #state{bitmap=Prev, canvas=Canvas}) ->
Bitmap = wxBitmap:new(W,H),
- draw(State#state.canvas, Bitmap, fun(DC) -> wxDC:clear(DC) end),
+ draw(Canvas, Bitmap, fun(DC) -> wxDC:clear(DC) end),
wxBitmap:destroy(Prev),
{noreply, State#state{bitmap = Bitmap}};
+
+handle_event(#wx{event = #wxMouse{type=left_down, x=X, y=Y}}, State) ->
+ {noreply, State#state{pos={X,Y}}};
+handle_event(#wx{event = #wxMouse{type=motion, x=X1, y=Y1}},
+ #state{pos=Start, overlay=Overlay, canvas=Canvas} = State) ->
+ case Start of
+ undefined -> ignore;
+ {X0,Y0} ->
+ DC = wxClientDC:new(Canvas),
+ DCO = wxDCOverlay:new(Overlay, DC),
+ wxDCOverlay:clear(DCO),
+ wxDC:setPen(DC, ?wxLIGHT_GREY_PEN),
+ wxDC:setBrush(DC, ?wxTRANSPARENT_BRUSH),
+ wxDC:drawRectangle(DC, {X0,Y0, X1-X0, Y1-Y0}),
+ wxDCOverlay:destroy(DCO),
+ wxClientDC:destroy(DC)
+ end,
+ {noreply, State};
+handle_event(#wx{event = #wxMouse{type=left_up}},
+ #state{overlay=Overlay, canvas=Canvas} = State) ->
+ DC = wxClientDC:new(Canvas),
+ DCO = wxDCOverlay:new(Overlay, DC),
+ wxDCOverlay:clear(DCO),
+ wxDCOverlay:destroy(DCO),
+ wxClientDC:destroy(DC),
+ wxOverlay:reset(Overlay),
+ {noreply, State#state{pos=undefined}};
+
handle_event(Ev = #wx{}, State = #state{}) ->
demo:format(State#state.config, "Got Event ~p\n", [Ev]),
{noreply, State}.
@@ -155,7 +191,8 @@ handle_cast(Msg, State) ->
code_change(_, _, State) ->
{stop, ignore, State}.
-terminate(_Reason, _) ->
+terminate(_Reason, #state{overlay=Overlay}) ->
+ wxOverlay:destroy(Overlay),
ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -182,4 +219,4 @@ redraw(DC, Bitmap) ->
wxMemoryDC:destroy(MemoryDC).
get_pos(W,H) ->
- {random:uniform(W), random:uniform(H)}.
+ {rand:uniform(W), rand:uniform(H)}.
diff --git a/lib/wx/examples/sudoku/sudoku_game.erl b/lib/wx/examples/sudoku/sudoku_game.erl
index e3c39b4ec9..8bb5fe4d38 100644
--- a/lib/wx/examples/sudoku/sudoku_game.erl
+++ b/lib/wx/examples/sudoku/sudoku_game.erl
@@ -151,8 +151,7 @@ test() -> %% Known to solvable
{{9,2},4}, {{9,4},5}, {{9,6},8}, {{9,8},7}].
new_game(S) ->
- {X,Y,Z} = erlang:now(),
- random:seed(Y,X,Z),
+ rand:seed(exsplus),
case new_game(1,1,gb_sets:empty(),empty_table(S#s{}),[], 0) of
stop -> new_game(S);
Game -> Game
@@ -171,7 +170,7 @@ new_game(R,C,BT,St,Acc,Cnt) when R < 10, C < 10 ->
[{{BR,BC},BVal,BBT,BST}|BAcc] = Acc,
new_game(BR,BC,gb_sets:add(BVal,BBT),BST,BAcc,Cnt+1);
Size ->
- Ind = random:uniform(Size),
+ Ind = rand:uniform(Size),
V = lists:nth(Ind,gb_sets:to_list(S)),
new_game(R,C+1,gb_sets:empty(),
add({R,C,M},V,St),
@@ -207,7 +206,7 @@ pick_shown(Given,Left,S0,Level,Gfx) ->
io:format("Below level ~p ~p~n", [GivenSz,Level]),
S0;
true ->
- Ran = random:uniform(LeftSz),
+ Ran = rand:uniform(LeftSz),
V = lists:nth(Ran,gb_sets:to_list(Left)),
S1 = rebuild_all(rcm(V),S0#s{v=setelement(V,S0#s.v,0)}),
case solve(S1, true) of
diff --git a/lib/wx/src/gen/gl.erl b/lib/wx/src/gen/gl.erl
index 58cdb59aa2..bedd4e9cca 100644
--- a/lib/wx/src/gen/gl.erl
+++ b/lib/wx/src/gen/gl.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2015. All 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,10 +53,14 @@
-type enum() :: non_neg_integer(). %% See wx/include/gl.hrl
-type clamp() :: float(). %% 0.0..1.0
-type offset() :: non_neg_integer(). %% Offset in memory block
--type matrix() :: {float(),float(),float(),float(),
+-type matrix12() :: {float(),float(),float(),float(),
+ float(),float(),float(),float(),
+ float(),float(),float(),float()}.
+-type matrix16() :: {float(),float(),float(),float(),
float(),float(),float(),float(),
float(),float(),float(),float(),
float(),float(),float(),float()}.
+-type matrix() :: matrix12() | matrix16().
-type mem() :: binary() | tuple(). %% Memory block
-export([clearIndex/1,clearColor/4,clear/1,indexMask/1,colorMask/4,alphaFunc/2,
@@ -4289,14 +4293,14 @@ lighti(Light,Pname,Param) ->
%% @doc
%% See {@link lightf/3}
--spec lightfv(Light, Pname, Params) -> ok when Light :: enum(),Pname :: enum(),Params :: {float()}.
+-spec lightfv(Light, Pname, Params) -> ok when Light :: enum(),Pname :: enum(),Params :: tuple().
lightfv(Light,Pname,Params) ->
cast(5207, <<Light:?GLenum,Pname:?GLenum,(size(Params)):?GLuint,
(<< <<C:?GLfloat>> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>).
%% @doc
%% See {@link lightf/3}
--spec lightiv(Light, Pname, Params) -> ok when Light :: enum(),Pname :: enum(),Params :: {integer()}.
+-spec lightiv(Light, Pname, Params) -> ok when Light :: enum(),Pname :: enum(),Params :: tuple().
lightiv(Light,Pname,Params) ->
cast(5208, <<Light:?GLenum,Pname:?GLenum,(size(Params)):?GLuint,
(<< <<C:?GLint>> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>).
@@ -4460,14 +4464,14 @@ lightModeli(Pname,Param) ->
%% @doc
%% See {@link lightModelf/2}
--spec lightModelfv(Pname, Params) -> ok when Pname :: enum(),Params :: {float()}.
+-spec lightModelfv(Pname, Params) -> ok when Pname :: enum(),Params :: tuple().
lightModelfv(Pname,Params) ->
cast(5213, <<Pname:?GLenum,(size(Params)):?GLuint,
(<< <<C:?GLfloat>> ||C <- tuple_to_list(Params)>>)/binary,0:(((0+size(Params)) rem 2)*32)>>).
%% @doc
%% See {@link lightModelf/2}
--spec lightModeliv(Pname, Params) -> ok when Pname :: enum(),Params :: {integer()}.
+-spec lightModeliv(Pname, Params) -> ok when Pname :: enum(),Params :: tuple().
lightModeliv(Pname,Params) ->
cast(5214, <<Pname:?GLenum,(size(Params)):?GLuint,
(<< <<C:?GLint>> ||C <- tuple_to_list(Params)>>)/binary,0:(((0+size(Params)) rem 2)*32)>>).
@@ -4547,14 +4551,14 @@ materiali(Face,Pname,Param) ->
%% @doc
%% See {@link materialf/3}
--spec materialfv(Face, Pname, Params) -> ok when Face :: enum(),Pname :: enum(),Params :: {float()}.
+-spec materialfv(Face, Pname, Params) -> ok when Face :: enum(),Pname :: enum(),Params :: tuple().
materialfv(Face,Pname,Params) ->
cast(5217, <<Face:?GLenum,Pname:?GLenum,(size(Params)):?GLuint,
(<< <<C:?GLfloat>> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>).
%% @doc
%% See {@link materialf/3}
--spec materialiv(Face, Pname, Params) -> ok when Face :: enum(),Pname :: enum(),Params :: {integer()}.
+-spec materialiv(Face, Pname, Params) -> ok when Face :: enum(),Pname :: enum(),Params :: tuple().
materialiv(Face,Pname,Params) ->
cast(5218, <<Face:?GLenum,Pname:?GLenum,(size(Params)):?GLuint,
(<< <<C:?GLint>> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>).
@@ -5890,21 +5894,21 @@ texGeni(Coord,Pname,Param) ->
%% @doc
%% See {@link texGend/3}
--spec texGendv(Coord, Pname, Params) -> ok when Coord :: enum(),Pname :: enum(),Params :: {float()}.
+-spec texGendv(Coord, Pname, Params) -> ok when Coord :: enum(),Pname :: enum(),Params :: tuple().
texGendv(Coord,Pname,Params) ->
cast(5246, <<Coord:?GLenum,Pname:?GLenum,(size(Params)):?GLuint,0:32,
(<< <<C:?GLdouble>> ||C <- tuple_to_list(Params)>>)/binary>>).
%% @doc
%% See {@link texGend/3}
--spec texGenfv(Coord, Pname, Params) -> ok when Coord :: enum(),Pname :: enum(),Params :: {float()}.
+-spec texGenfv(Coord, Pname, Params) -> ok when Coord :: enum(),Pname :: enum(),Params :: tuple().
texGenfv(Coord,Pname,Params) ->
cast(5247, <<Coord:?GLenum,Pname:?GLenum,(size(Params)):?GLuint,
(<< <<C:?GLfloat>> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>).
%% @doc
%% See {@link texGend/3}
--spec texGeniv(Coord, Pname, Params) -> ok when Coord :: enum(),Pname :: enum(),Params :: {integer()}.
+-spec texGeniv(Coord, Pname, Params) -> ok when Coord :: enum(),Pname :: enum(),Params :: tuple().
texGeniv(Coord,Pname,Params) ->
cast(5248, <<Coord:?GLenum,Pname:?GLenum,(size(Params)):?GLuint,
(<< <<C:?GLint>> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>).
@@ -6123,14 +6127,14 @@ texEnvi(Target,Pname,Param) ->
%% replacement. The default value is `?GL_FALSE'.
%%
%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexEnv.xml">external</a> documentation.
--spec texEnvfv(Target, Pname, Params) -> ok when Target :: enum(),Pname :: enum(),Params :: {float()}.
+-spec texEnvfv(Target, Pname, Params) -> ok when Target :: enum(),Pname :: enum(),Params :: tuple().
texEnvfv(Target,Pname,Params) ->
cast(5254, <<Target:?GLenum,Pname:?GLenum,(size(Params)):?GLuint,
(<< <<C:?GLfloat>> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>).
%% @doc
%% See {@link texEnvfv/3}
--spec texEnviv(Target, Pname, Params) -> ok when Target :: enum(),Pname :: enum(),Params :: {integer()}.
+-spec texEnviv(Target, Pname, Params) -> ok when Target :: enum(),Pname :: enum(),Params :: tuple().
texEnviv(Target,Pname,Params) ->
cast(5255, <<Target:?GLenum,Pname:?GLenum,(size(Params)):?GLuint,
(<< <<C:?GLint>> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>).
@@ -6455,14 +6459,14 @@ texParameteri(Target,Pname,Param) ->
%% @doc
%% See {@link texParameterf/3}
--spec texParameterfv(Target, Pname, Params) -> ok when Target :: enum(),Pname :: enum(),Params :: {float()}.
+-spec texParameterfv(Target, Pname, Params) -> ok when Target :: enum(),Pname :: enum(),Params :: tuple().
texParameterfv(Target,Pname,Params) ->
cast(5260, <<Target:?GLenum,Pname:?GLenum,(size(Params)):?GLuint,
(<< <<C:?GLfloat>> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>).
%% @doc
%% See {@link texParameterf/3}
--spec texParameteriv(Target, Pname, Params) -> ok when Target :: enum(),Pname :: enum(),Params :: {integer()}.
+-spec texParameteriv(Target, Pname, Params) -> ok when Target :: enum(),Pname :: enum(),Params :: tuple().
texParameteriv(Target,Pname,Params) ->
cast(5261, <<Target:?GLenum,Pname:?GLenum,(size(Params)):?GLuint,
(<< <<C:?GLint>> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>).
@@ -7609,14 +7613,14 @@ fogi(Pname,Param) ->
%% @doc
%% See {@link fogf/2}
--spec fogfv(Pname, Params) -> ok when Pname :: enum(),Params :: {float()}.
+-spec fogfv(Pname, Params) -> ok when Pname :: enum(),Params :: tuple().
fogfv(Pname,Params) ->
cast(5306, <<Pname:?GLenum,(size(Params)):?GLuint,
(<< <<C:?GLfloat>> ||C <- tuple_to_list(Params)>>)/binary,0:(((0+size(Params)) rem 2)*32)>>).
%% @doc
%% See {@link fogf/2}
--spec fogiv(Pname, Params) -> ok when Pname :: enum(),Params :: {integer()}.
+-spec fogiv(Pname, Params) -> ok when Pname :: enum(),Params :: tuple().
fogiv(Pname,Params) ->
cast(5307, <<Pname:?GLenum,(size(Params)):?GLuint,
(<< <<C:?GLint>> ||C <- tuple_to_list(Params)>>)/binary,0:(((0+size(Params)) rem 2)*32)>>).
@@ -8522,24 +8526,24 @@ convolutionFilter2D(Target,Internalformat,Width,Height,Format,Type,Image) ->
%% image were replicated.
%%
%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glConvolutionParameter.xml">external</a> documentation.
--spec convolutionParameterf(Target, Pname, Params) -> ok when Target :: enum(),Pname :: enum(),Params :: {float()}.
+-spec convolutionParameterf(Target, Pname, Params) -> ok when Target :: enum(),Pname :: enum(),Params :: tuple().
convolutionParameterf(Target,Pname,Params) ->
cast(5339, <<Target:?GLenum,Pname:?GLenum,(size(Params)):?GLuint,
(<< <<C:?GLfloat>> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>).
%% @equiv convolutionParameterf(Target,Pname,Params)
--spec convolutionParameterfv(Target :: enum(),Pname :: enum(),Params) -> ok when Params :: {Params :: {float()}}.
+-spec convolutionParameterfv(Target :: enum(),Pname :: enum(),Params) -> ok when Params :: {Params :: tuple()}.
convolutionParameterfv(Target,Pname,{Params}) -> convolutionParameterf(Target,Pname,Params).
%% @doc
%% See {@link convolutionParameterf/3}
--spec convolutionParameteri(Target, Pname, Params) -> ok when Target :: enum(),Pname :: enum(),Params :: {integer()}.
+-spec convolutionParameteri(Target, Pname, Params) -> ok when Target :: enum(),Pname :: enum(),Params :: tuple().
convolutionParameteri(Target,Pname,Params) ->
cast(5340, <<Target:?GLenum,Pname:?GLenum,(size(Params)):?GLuint,
(<< <<C:?GLint>> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>).
%% @equiv convolutionParameteri(Target,Pname,Params)
--spec convolutionParameteriv(Target :: enum(),Pname :: enum(),Params) -> ok when Params :: {Params :: {integer()}}.
+-spec convolutionParameteriv(Target :: enum(),Pname :: enum(),Params) -> ok when Params :: {Params :: tuple()}.
convolutionParameteriv(Target,Pname,{Params}) -> convolutionParameteri(Target,Pname,Params).
%% @doc Copy pixels into a one-dimensional convolution filter
@@ -9671,7 +9675,7 @@ pointParameterf(Pname,Param) ->
%% @doc
%% See {@link pointParameterf/2}
--spec pointParameterfv(Pname, Params) -> ok when Pname :: enum(),Params :: {float()}.
+-spec pointParameterfv(Pname, Params) -> ok when Pname :: enum(),Params :: tuple().
pointParameterfv(Pname,Params) ->
cast(5397, <<Pname:?GLenum,(size(Params)):?GLuint,
(<< <<C:?GLfloat>> ||C <- tuple_to_list(Params)>>)/binary,0:(((0+size(Params)) rem 2)*32)>>).
@@ -9684,7 +9688,7 @@ pointParameteri(Pname,Param) ->
%% @doc
%% See {@link pointParameterf/2}
--spec pointParameteriv(Pname, Params) -> ok when Pname :: enum(),Params :: {integer()}.
+-spec pointParameteriv(Pname, Params) -> ok when Pname :: enum(),Params :: tuple().
pointParameteriv(Pname,Params) ->
cast(5399, <<Pname:?GLenum,(size(Params)):?GLuint,
(<< <<C:?GLint>> ||C <- tuple_to_list(Params)>>)/binary,0:(((0+size(Params)) rem 2)*32)>>).
@@ -11529,7 +11533,7 @@ linkProgram(Program) ->
%% scanned or parsed at this time; they are simply copied into the specified shader object.
%%
%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glShaderSource.xml">external</a> documentation.
--spec shaderSource(Shader, String) -> ok when Shader :: integer(),String :: [string()].
+-spec shaderSource(Shader, String) -> ok when Shader :: integer(),String :: iolist().
shaderSource(Shader,String) ->
StringTemp = list_to_binary([[Str|[0]] || Str <- String ]),
cast(5473, <<Shader:?GLuint,(length(String)):?GLuint,(size(StringTemp)):?GLuint,(StringTemp)/binary,0:((8-((size(StringTemp)+0) rem 8)) rem 8)>>).
@@ -12278,7 +12282,7 @@ bindBufferBase(Target,Index,Buffer) ->
%% and the buffer mode is `?GL_INTERLEAVED_ATTRIBS'.
%%
%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTransformFeedbackVaryings.xml">external</a> documentation.
--spec transformFeedbackVaryings(Program, Varyings, BufferMode) -> ok when Program :: integer(),Varyings :: [string()],BufferMode :: enum().
+-spec transformFeedbackVaryings(Program, Varyings, BufferMode) -> ok when Program :: integer(),Varyings :: iolist(),BufferMode :: enum().
transformFeedbackVaryings(Program,Varyings,BufferMode) ->
VaryingsTemp = list_to_binary([[Str|[0]] || Str <- Varyings ]),
cast(5536, <<Program:?GLuint,(length(Varyings)):?GLuint,(size(VaryingsTemp)):?GLuint,(VaryingsTemp)/binary,0:((8-((size(VaryingsTemp)+0) rem 8)) rem 8),BufferMode:?GLenum>>).
@@ -12596,7 +12600,7 @@ uniform4uiv(Location,Value) ->
%% @doc
%% See {@link texParameterf/3}
--spec texParameterIiv(Target, Pname, Params) -> ok when Target :: enum(),Pname :: enum(),Params :: {integer()}.
+-spec texParameterIiv(Target, Pname, Params) -> ok when Target :: enum(),Pname :: enum(),Params :: tuple().
texParameterIiv(Target,Pname,Params) ->
cast(5568, <<Target:?GLenum,Pname:?GLenum,(size(Params)):?GLuint,
(<< <<C:?GLint>> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>).
@@ -12604,7 +12608,7 @@ texParameterIiv(Target,Pname,Params) ->
%% @doc glTexParameterI
%%
%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexParameterI.xml">external</a> documentation.
--spec texParameterIuiv(Target, Pname, Params) -> ok when Target :: enum(),Pname :: enum(),Params :: {integer()}.
+-spec texParameterIuiv(Target, Pname, Params) -> ok when Target :: enum(),Pname :: enum(),Params :: tuple().
texParameterIuiv(Target,Pname,Params) ->
cast(5569, <<Target:?GLenum,Pname:?GLenum,(size(Params)):?GLuint,
(<< <<C:?GLuint>> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>).
@@ -12651,21 +12655,21 @@ getTexParameterIuiv(Target,Pname) ->
%% and the buffer being cleared is defined. However, this is not an error.
%%
%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glClearBuffer.xml">external</a> documentation.
--spec clearBufferiv(Buffer, Drawbuffer, Value) -> ok when Buffer :: enum(),Drawbuffer :: integer(),Value :: {integer()}.
+-spec clearBufferiv(Buffer, Drawbuffer, Value) -> ok when Buffer :: enum(),Drawbuffer :: integer(),Value :: tuple().
clearBufferiv(Buffer,Drawbuffer,Value) ->
cast(5572, <<Buffer:?GLenum,Drawbuffer:?GLint,(size(Value)):?GLuint,
(<< <<C:?GLint>> ||C <- tuple_to_list(Value)>>)/binary,0:(((1+size(Value)) rem 2)*32)>>).
%% @doc
%% See {@link clearBufferiv/3}
--spec clearBufferuiv(Buffer, Drawbuffer, Value) -> ok when Buffer :: enum(),Drawbuffer :: integer(),Value :: {integer()}.
+-spec clearBufferuiv(Buffer, Drawbuffer, Value) -> ok when Buffer :: enum(),Drawbuffer :: integer(),Value :: tuple().
clearBufferuiv(Buffer,Drawbuffer,Value) ->
cast(5573, <<Buffer:?GLenum,Drawbuffer:?GLint,(size(Value)):?GLuint,
(<< <<C:?GLuint>> ||C <- tuple_to_list(Value)>>)/binary,0:(((1+size(Value)) rem 2)*32)>>).
%% @doc
%% See {@link clearBufferiv/3}
--spec clearBufferfv(Buffer, Drawbuffer, Value) -> ok when Buffer :: enum(),Drawbuffer :: integer(),Value :: {float()}.
+-spec clearBufferfv(Buffer, Drawbuffer, Value) -> ok when Buffer :: enum(),Drawbuffer :: integer(),Value :: tuple().
clearBufferfv(Buffer,Drawbuffer,Value) ->
cast(5574, <<Buffer:?GLenum,Drawbuffer:?GLint,(size(Value)):?GLuint,
(<< <<C:?GLfloat>> ||C <- tuple_to_list(Value)>>)/binary,0:(((1+size(Value)) rem 2)*32)>>).
@@ -13219,7 +13223,7 @@ createShaderObjectARB(ShaderType) ->
%% @doc glShaderSourceARB
%%
%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glShaderSourceARB.xml">external</a> documentation.
--spec shaderSourceARB(ShaderObj, String) -> ok when ShaderObj :: integer(),String :: [string()].
+-spec shaderSourceARB(ShaderObj, String) -> ok when ShaderObj :: integer(),String :: iolist().
shaderSourceARB(ShaderObj,String) ->
StringTemp = list_to_binary([[Str|[0]] || Str <- String ]),
cast(5630, <<ShaderObj:?GLhandleARB,(length(String)):?GLuint,(size(StringTemp)):?GLuint,(StringTemp)/binary,0:((8-((size(StringTemp)+4) rem 8)) rem 8)>>).
@@ -13927,7 +13931,7 @@ isVertexArray(Array) ->
%% If an error occurs, nothing is written to `UniformIndices' .
%%
%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetUniformIndices.xml">external</a> documentation.
--spec getUniformIndices(Program, UniformNames) -> [integer()] when Program :: integer(),UniformNames :: [string()].
+-spec getUniformIndices(Program, UniformNames) -> [integer()] when Program :: integer(),UniformNames :: iolist().
getUniformIndices(Program,UniformNames) ->
UniformNamesTemp = list_to_binary([[Str|[0]] || Str <- UniformNames ]),
call(5675, <<Program:?GLuint,(length(UniformNames)):?GLuint,(size(UniformNamesTemp)):?GLuint,(UniformNamesTemp)/binary,0:((8-((size(UniformNamesTemp)+0) rem 8)) rem 8)>>).
@@ -14458,7 +14462,7 @@ deleteNamedStringARB(Name) ->
%% @doc glCompileShaderIncludeARB
%%
%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCompileShaderIncludeARB.xml">external</a> documentation.
--spec compileShaderIncludeARB(Shader, Path) -> ok when Shader :: integer(),Path :: [string()].
+-spec compileShaderIncludeARB(Shader, Path) -> ok when Shader :: integer(),Path :: iolist().
compileShaderIncludeARB(Shader,Path) ->
PathTemp = list_to_binary([[Str|[0]] || Str <- Path ]),
cast(5703, <<Shader:?GLuint,(length(Path)):?GLuint,(size(PathTemp)):?GLuint,(PathTemp)/binary,0:((8-((size(PathTemp)+0) rem 8)) rem 8)>>).
@@ -15617,7 +15621,7 @@ activeShaderProgram(Pipeline,Program) ->
%% @doc glCreateShaderProgramv
%%
%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCreateShaderProgramv.xml">external</a> documentation.
--spec createShaderProgramv(Type, Strings) -> integer() when Type :: enum(),Strings :: [string()].
+-spec createShaderProgramv(Type, Strings) -> integer() when Type :: enum(),Strings :: iolist().
createShaderProgramv(Type,Strings) ->
StringsTemp = list_to_binary([[Str|[0]] || Str <- Strings ]),
call(5778, <<Type:?GLenum,(length(Strings)):?GLuint,(size(StringsTemp)):?GLuint,(StringsTemp)/binary,0:((8-((size(StringsTemp)+0) rem 8)) rem 8)>>).
diff --git a/lib/wx/src/gen/glu.erl b/lib/wx/src/gen/glu.erl
index 6a6e20b3e4..5faba48930 100644
--- a/lib/wx/src/gen/glu.erl
+++ b/lib/wx/src/gen/glu.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2015. All 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,10 +51,14 @@
-define(GLint64,64/native-signed).
-type vertex() :: {float(), float(), float()}.
-type enum() :: non_neg_integer(). %% See wx/include/gl.hrl or glu.hrl
--type matrix() :: {float(),float(),float(),float(),
+-type matrix12() :: {float(),float(),float(),float(),
+ float(),float(),float(),float(),
+ float(),float(),float(),float()}.
+-type matrix16() :: {float(),float(),float(),float(),
float(),float(),float(),float(),
float(),float(),float(),float(),
float(),float(),float(),float()}.
+-type matrix() :: matrix12() | matrix16().
-type mem() :: binary() | tuple(). %% Memory block
-export([tesselate/2,build1DMipmapLevels/9,build1DMipmaps/6,build2DMipmapLevels/10,
diff --git a/lib/wx/src/gen/wxDCOverlay.erl b/lib/wx/src/gen/wxDCOverlay.erl
new file mode 100644
index 0000000000..f98e310ba6
--- /dev/null
+++ b/lib/wx/src/gen/wxDCOverlay.erl
@@ -0,0 +1,70 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2008-2015. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%% This file is generated DO NOT EDIT
+
+%% @doc See external documentation: <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxdcoverlay.html">wxDCOverlay</a>.
+%% @type wxDCOverlay(). An object reference, The representation is internal
+%% and can be changed without notice. It can't be used for comparsion
+%% stored on disc or distributed for use on other nodes.
+
+-module(wxDCOverlay).
+-include("wxe.hrl").
+-export([clear/1,destroy/1,new/2,new/6]).
+
+%% inherited exports
+-export([parent_class/1]).
+
+-export_type([wxDCOverlay/0]).
+%% @hidden
+parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
+
+-type wxDCOverlay() :: wx:wx_object().
+%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxdcoverlay.html#wxdcoverlaywxdcoverlay">external documentation</a>.
+-spec new(Overlay, Dc) -> wxDCOverlay() when
+ Overlay::wxOverlay:wxOverlay(), Dc::wxWindowDC:wxWindowDC().
+new(#wx_ref{type=OverlayT,ref=OverlayRef},#wx_ref{type=DcT,ref=DcRef}) ->
+ ?CLASS(OverlayT,wxOverlay),
+ ?CLASS(DcT,wxWindowDC),
+ wxe_util:construct(?wxDCOverlay_new_2,
+ <<OverlayRef:32/?UI,DcRef:32/?UI>>).
+
+%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxdcoverlay.html#wxdcoverlaywxdcoverlay">external documentation</a>.
+-spec new(Overlay, Dc, X, Y, Width, Height) -> wxDCOverlay() when
+ Overlay::wxOverlay:wxOverlay(), Dc::wxWindowDC:wxWindowDC(), X::integer(), Y::integer(), Width::integer(), Height::integer().
+new(#wx_ref{type=OverlayT,ref=OverlayRef},#wx_ref{type=DcT,ref=DcRef},X,Y,Width,Height)
+ when is_integer(X),is_integer(Y),is_integer(Width),is_integer(Height) ->
+ ?CLASS(OverlayT,wxOverlay),
+ ?CLASS(DcT,wxWindowDC),
+ wxe_util:construct(?wxDCOverlay_new_6,
+ <<OverlayRef:32/?UI,DcRef:32/?UI,X:32/?UI,Y:32/?UI,Width:32/?UI,Height:32/?UI>>).
+
+%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxdcoverlay.html#wxdcoverlayclear">external documentation</a>.
+-spec clear(This) -> ok when
+ This::wxDCOverlay().
+clear(#wx_ref{type=ThisT,ref=ThisRef}) ->
+ ?CLASS(ThisT,wxDCOverlay),
+ wxe_util:cast(?wxDCOverlay_Clear,
+ <<ThisRef:32/?UI>>).
+
+%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxDCOverlay()) -> ok.
+destroy(Obj=#wx_ref{type=Type}) ->
+ ?CLASS(Type,wxDCOverlay),
+ wxe_util:destroy(?wxDCOverlay_destruct,Obj),
+ ok.
diff --git a/lib/wx/src/gen/wxOverlay.erl b/lib/wx/src/gen/wxOverlay.erl
new file mode 100644
index 0000000000..7da3ece657
--- /dev/null
+++ b/lib/wx/src/gen/wxOverlay.erl
@@ -0,0 +1,57 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2008-2015. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%% This file is generated DO NOT EDIT
+
+%% @doc See external documentation: <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxoverlay.html">wxOverlay</a>.
+%% @type wxOverlay(). An object reference, The representation is internal
+%% and can be changed without notice. It can't be used for comparsion
+%% stored on disc or distributed for use on other nodes.
+
+-module(wxOverlay).
+-include("wxe.hrl").
+-export([destroy/1,new/0,reset/1]).
+
+%% inherited exports
+-export([parent_class/1]).
+
+-export_type([wxOverlay/0]).
+%% @hidden
+parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
+
+-type wxOverlay() :: wx:wx_object().
+%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxoverlay.html#wxoverlaywxoverlay">external documentation</a>.
+-spec new() -> wxOverlay().
+new() ->
+ wxe_util:construct(?wxOverlay_new,
+ <<>>).
+
+%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxoverlay.html#wxoverlayreset">external documentation</a>.
+-spec reset(This) -> ok when
+ This::wxOverlay().
+reset(#wx_ref{type=ThisT,ref=ThisRef}) ->
+ ?CLASS(ThisT,wxOverlay),
+ wxe_util:cast(?wxOverlay_Reset,
+ <<ThisRef:32/?UI>>).
+
+%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxOverlay()) -> ok.
+destroy(Obj=#wx_ref{type=Type}) ->
+ ?CLASS(Type,wxOverlay),
+ wxe_util:destroy(?wxOverlay_destruct,Obj),
+ ok.
diff --git a/lib/wx/src/gen/wxToolBar.erl b/lib/wx/src/gen/wxToolBar.erl
index 5c079fec1e..bee20b97f4 100644
--- a/lib/wx/src/gen/wxToolBar.erl
+++ b/lib/wx/src/gen/wxToolBar.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2015. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -31,14 +31,15 @@
-module(wxToolBar).
-include("wxe.hrl").
-export([addCheckTool/4,addCheckTool/5,addControl/2,addRadioTool/4,addRadioTool/5,
- addSeparator/1,addTool/2,addTool/3,addTool/4,addTool/5,addTool/6,addTool/7,
- deleteTool/2,deleteToolByPos/2,enableTool/3,findById/2,findControl/2,
- findToolForPosition/3,getMargins/1,getToolBitmapSize/1,getToolEnabled/2,
- getToolLongHelp/2,getToolPacking/1,getToolPos/2,getToolSeparation/1,
- getToolShortHelp/2,getToolSize/1,getToolState/2,insertControl/3,insertSeparator/2,
- insertTool/3,insertTool/4,insertTool/5,insertTool/6,realize/1,removeTool/2,
- setMargins/3,setToolBitmapSize/2,setToolLongHelp/3,setToolPacking/2,
- setToolSeparation/2,setToolShortHelp/3,toggleTool/3]).
+ addSeparator/1,addStretchableSpace/1,addTool/2,addTool/3,addTool/4,
+ addTool/5,addTool/6,addTool/7,deleteTool/2,deleteToolByPos/2,enableTool/3,
+ findById/2,findControl/2,findToolForPosition/3,getMargins/1,getToolBitmapSize/1,
+ getToolEnabled/2,getToolLongHelp/2,getToolPacking/1,getToolPos/2,
+ getToolSeparation/1,getToolShortHelp/2,getToolSize/1,getToolState/2,
+ insertControl/3,insertSeparator/2,insertStretchableSpace/2,insertTool/3,
+ insertTool/4,insertTool/5,insertTool/6,realize/1,removeTool/2,setMargins/3,
+ setToolBitmapSize/2,setToolLongHelp/3,setToolPacking/2,setToolSeparation/2,
+ setToolShortHelp/3,toggleTool/3]).
%% inherited exports
-export([cacheBestSize/2,captureMouse/1,center/1,center/2,centerOnParent/1,
@@ -328,6 +329,23 @@ addRadioTool(#wx_ref{type=ThisT,ref=ThisRef},Toolid,Label,#wx_ref{type=BitmapT,r
wxe_util:call(?wxToolBar_AddRadioTool,
<<ThisRef:32/?UI,Toolid:32/?UI,(byte_size(Label_UC)):32/?UI,(Label_UC)/binary, 0:(((8- ((4+byte_size(Label_UC)) band 16#7)) band 16#7))/unit:8,BitmapRef:32/?UI, 0:32,BinOpt/binary>>).
+%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxtoolbar.html#wxtoolbaraddstretchablespace">external documentation</a>.
+-spec addStretchableSpace(This) -> wx:wx_object() when
+ This::wxToolBar().
+addStretchableSpace(#wx_ref{type=ThisT,ref=ThisRef}) ->
+ ?CLASS(ThisT,wxToolBar),
+ wxe_util:call(?wxToolBar_AddStretchableSpace,
+ <<ThisRef:32/?UI>>).
+
+%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxtoolbar.html#wxtoolbarinsertstretchablespace">external documentation</a>.
+-spec insertStretchableSpace(This, Pos) -> wx:wx_object() when
+ This::wxToolBar(), Pos::integer().
+insertStretchableSpace(#wx_ref{type=ThisT,ref=ThisRef},Pos)
+ when is_integer(Pos) ->
+ ?CLASS(ThisT,wxToolBar),
+ wxe_util:call(?wxToolBar_InsertStretchableSpace,
+ <<ThisRef:32/?UI,Pos:32/?UI>>).
+
%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxtoolbar.html#wxtoolbardeletetool">external documentation</a>.
-spec deleteTool(This, Toolid) -> boolean() when
This::wxToolBar(), Toolid::integer().
diff --git a/lib/wx/src/gen/wxe_debug.hrl b/lib/wx/src/gen/wxe_debug.hrl
index 2cb73c0fed..375adde47d 100644
--- a/lib/wx/src/gen/wxe_debug.hrl
+++ b/lib/wx/src/gen/wxe_debug.hrl
@@ -863,2506 +863,2515 @@ wxdebug_table() ->
{981, {wxToolBar, addTool_6, 6}},
{982, {wxToolBar, addCheckTool, 4}},
{983, {wxToolBar, addRadioTool, 4}},
- {984, {wxToolBar, deleteTool, 1}},
- {985, {wxToolBar, deleteToolByPos, 1}},
- {986, {wxToolBar, enableTool, 2}},
- {987, {wxToolBar, findById, 1}},
- {988, {wxToolBar, findControl, 1}},
- {989, {wxToolBar, findToolForPosition, 2}},
- {990, {wxToolBar, getToolSize, 0}},
- {991, {wxToolBar, getToolBitmapSize, 0}},
- {992, {wxToolBar, getMargins, 0}},
- {993, {wxToolBar, getToolEnabled, 1}},
- {994, {wxToolBar, getToolLongHelp, 1}},
- {995, {wxToolBar, getToolPacking, 0}},
- {996, {wxToolBar, getToolPos, 1}},
- {997, {wxToolBar, getToolSeparation, 0}},
- {998, {wxToolBar, getToolShortHelp, 1}},
- {999, {wxToolBar, getToolState, 1}},
- {1000, {wxToolBar, insertControl, 2}},
- {1001, {wxToolBar, insertSeparator, 1}},
- {1002, {wxToolBar, insertTool_5, 5}},
- {1003, {wxToolBar, insertTool_2, 2}},
- {1004, {wxToolBar, insertTool_4, 4}},
- {1005, {wxToolBar, realize, 0}},
- {1006, {wxToolBar, removeTool, 1}},
- {1007, {wxToolBar, setMargins, 2}},
- {1008, {wxToolBar, setToolBitmapSize, 1}},
- {1009, {wxToolBar, setToolLongHelp, 2}},
- {1010, {wxToolBar, setToolPacking, 1}},
- {1011, {wxToolBar, setToolShortHelp, 2}},
- {1012, {wxToolBar, setToolSeparation, 1}},
- {1013, {wxToolBar, toggleTool, 2}},
- {1015, {wxStatusBar, new_0, 0}},
- {1016, {wxStatusBar, new_2, 2}},
- {1018, {wxStatusBar, destruct, 0}},
- {1019, {wxStatusBar, create, 2}},
- {1020, {wxStatusBar, getFieldRect, 2}},
- {1021, {wxStatusBar, getFieldsCount, 0}},
- {1022, {wxStatusBar, getStatusText, 1}},
- {1023, {wxStatusBar, popStatusText, 1}},
- {1024, {wxStatusBar, pushStatusText, 2}},
- {1025, {wxStatusBar, setFieldsCount, 2}},
- {1026, {wxStatusBar, setMinHeight, 1}},
- {1027, {wxStatusBar, setStatusText, 2}},
- {1028, {wxStatusBar, setStatusWidths, 2}},
- {1029, {wxStatusBar, setStatusStyles, 2}},
- {1030, {wxBitmap, new_0, 0}},
- {1031, {wxBitmap, new_3, 3}},
- {1032, {wxBitmap, new_4, 4}},
- {1033, {wxBitmap, new_2_0, 2}},
- {1034, {wxBitmap, new_2_1, 2}},
- {1035, {wxBitmap, destruct, 0}},
- {1036, {wxBitmap, convertToImage, 0}},
- {1037, {wxBitmap, copyFromIcon, 1}},
- {1038, {wxBitmap, create, 3}},
- {1039, {wxBitmap, getDepth, 0}},
- {1040, {wxBitmap, getHeight, 0}},
- {1041, {wxBitmap, getPalette, 0}},
- {1042, {wxBitmap, getMask, 0}},
- {1043, {wxBitmap, getWidth, 0}},
- {1044, {wxBitmap, getSubBitmap, 1}},
- {1045, {wxBitmap, loadFile, 2}},
- {1046, {wxBitmap, ok, 0}},
- {1047, {wxBitmap, saveFile, 3}},
- {1048, {wxBitmap, setDepth, 1}},
- {1049, {wxBitmap, setHeight, 1}},
- {1050, {wxBitmap, setMask, 1}},
- {1051, {wxBitmap, setPalette, 1}},
- {1052, {wxBitmap, setWidth, 1}},
- {1053, {wxIcon, new_0, 0}},
- {1054, {wxIcon, new_2, 2}},
- {1055, {wxIcon, new_1, 1}},
- {1056, {wxIcon, copyFromBitmap, 1}},
- {1057, {wxIcon, 'Destroy', undefined}},
- {1058, {wxIconBundle, new_0, 0}},
- {1059, {wxIconBundle, new_2, 2}},
- {1060, {wxIconBundle, new_1_0, 1}},
- {1061, {wxIconBundle, new_1_1, 1}},
- {1062, {wxIconBundle, destruct, 0}},
- {1063, {wxIconBundle, addIcon_2, 2}},
- {1064, {wxIconBundle, addIcon_1, 1}},
- {1065, {wxIconBundle, getIcon_1_1, 1}},
- {1066, {wxIconBundle, getIcon_1_0, 1}},
- {1067, {wxCursor, new_0, 0}},
- {1068, {wxCursor, new_1_0, 1}},
- {1069, {wxCursor, new_1_1, 1}},
- {1070, {wxCursor, new_4, 4}},
- {1071, {wxCursor, destruct, 0}},
- {1072, {wxCursor, ok, 0}},
- {1073, {wxMask, new_0, 0}},
- {1074, {wxMask, new_2_1, 2}},
- {1075, {wxMask, new_2_0, 2}},
- {1076, {wxMask, new_1, 1}},
- {1077, {wxMask, destruct, 0}},
- {1078, {wxMask, create_2_1, 2}},
- {1079, {wxMask, create_2_0, 2}},
- {1080, {wxMask, create_1, 1}},
- {1081, {wxImage, new_0, 0}},
- {1082, {wxImage, new_3_0, 3}},
- {1083, {wxImage, new_4, 4}},
- {1084, {wxImage, new_5, 5}},
- {1085, {wxImage, new_2, 2}},
- {1086, {wxImage, new_3_1, 3}},
- {1087, {wxImage, blur, 1}},
- {1088, {wxImage, blurHorizontal, 1}},
- {1089, {wxImage, blurVertical, 1}},
- {1090, {wxImage, convertAlphaToMask, 1}},
- {1091, {wxImage, convertToGreyscale, 1}},
- {1092, {wxImage, convertToMono, 3}},
- {1093, {wxImage, copy, 0}},
- {1094, {wxImage, create_3, 3}},
- {1095, {wxImage, create_4, 4}},
- {1096, {wxImage, create_5, 5}},
- {1097, {wxImage, 'Destroy', 0}},
- {1098, {wxImage, findFirstUnusedColour, 4}},
- {1099, {wxImage, getImageExtWildcard, 0}},
- {1100, {wxImage, getAlpha_2, 2}},
- {1101, {wxImage, getAlpha_0, 0}},
- {1102, {wxImage, getBlue, 2}},
- {1103, {wxImage, getData, 0}},
- {1104, {wxImage, getGreen, 2}},
- {1105, {wxImage, getImageCount, 2}},
- {1106, {wxImage, getHeight, 0}},
- {1107, {wxImage, getMaskBlue, 0}},
- {1108, {wxImage, getMaskGreen, 0}},
- {1109, {wxImage, getMaskRed, 0}},
- {1110, {wxImage, getOrFindMaskColour, 3}},
- {1111, {wxImage, getPalette, 0}},
- {1112, {wxImage, getRed, 2}},
- {1113, {wxImage, getSubImage, 1}},
- {1114, {wxImage, getWidth, 0}},
- {1115, {wxImage, hasAlpha, 0}},
- {1116, {wxImage, hasMask, 0}},
- {1117, {wxImage, getOption, 1}},
- {1118, {wxImage, getOptionInt, 1}},
- {1119, {wxImage, hasOption, 1}},
- {1120, {wxImage, initAlpha, 0}},
- {1121, {wxImage, initStandardHandlers, 0}},
- {1122, {wxImage, isTransparent, 3}},
- {1123, {wxImage, loadFile_2, 2}},
- {1124, {wxImage, loadFile_3, 3}},
- {1125, {wxImage, ok, 0}},
- {1126, {wxImage, removeHandler, 1}},
- {1127, {wxImage, mirror, 1}},
- {1128, {wxImage, replace, 6}},
- {1129, {wxImage, rescale, 3}},
- {1130, {wxImage, resize, 3}},
- {1131, {wxImage, rotate, 3}},
- {1132, {wxImage, rotateHue, 1}},
- {1133, {wxImage, rotate90, 1}},
- {1134, {wxImage, saveFile_1, 1}},
- {1135, {wxImage, saveFile_2_0, 2}},
- {1136, {wxImage, saveFile_2_1, 2}},
- {1137, {wxImage, scale, 3}},
- {1138, {wxImage, size, 3}},
- {1139, {wxImage, setAlpha_3, 3}},
- {1140, {wxImage, setAlpha_2, 2}},
- {1141, {wxImage, setData_2, 2}},
- {1142, {wxImage, setData_4, 4}},
- {1143, {wxImage, setMask, 1}},
- {1144, {wxImage, setMaskColour, 3}},
- {1145, {wxImage, setMaskFromImage, 4}},
- {1146, {wxImage, setOption_2_1, 2}},
- {1147, {wxImage, setOption_2_0, 2}},
- {1148, {wxImage, setPalette, 1}},
- {1149, {wxImage, setRGB_5, 5}},
- {1150, {wxImage, setRGB_4, 4}},
- {1151, {wxImage, 'Destroy', undefined}},
- {1152, {wxBrush, new_0, 0}},
- {1153, {wxBrush, new_2, 2}},
- {1154, {wxBrush, new_1, 1}},
- {1156, {wxBrush, destruct, 0}},
- {1157, {wxBrush, getColour, 0}},
- {1158, {wxBrush, getStipple, 0}},
- {1159, {wxBrush, getStyle, 0}},
- {1160, {wxBrush, isHatch, 0}},
- {1161, {wxBrush, isOk, 0}},
- {1162, {wxBrush, setColour_1, 1}},
- {1163, {wxBrush, setColour_3, 3}},
- {1164, {wxBrush, setStipple, 1}},
- {1165, {wxBrush, setStyle, 1}},
- {1166, {wxPen, new_0, 0}},
- {1167, {wxPen, new_2, 2}},
- {1168, {wxPen, destruct, 0}},
- {1169, {wxPen, getCap, 0}},
- {1170, {wxPen, getColour, 0}},
- {1171, {wxPen, getJoin, 0}},
- {1172, {wxPen, getStyle, 0}},
- {1173, {wxPen, getWidth, 0}},
- {1174, {wxPen, isOk, 0}},
- {1175, {wxPen, setCap, 1}},
- {1176, {wxPen, setColour_1, 1}},
- {1177, {wxPen, setColour_3, 3}},
- {1178, {wxPen, setJoin, 1}},
- {1179, {wxPen, setStyle, 1}},
- {1180, {wxPen, setWidth, 1}},
- {1181, {wxRegion, new_0, 0}},
- {1182, {wxRegion, new_4, 4}},
- {1183, {wxRegion, new_2, 2}},
- {1184, {wxRegion, new_1_1, 1}},
- {1186, {wxRegion, new_1_0, 1}},
- {1188, {wxRegion, destruct, 0}},
- {1189, {wxRegion, clear, 0}},
- {1190, {wxRegion, contains_2, 2}},
- {1191, {wxRegion, contains_1_0, 1}},
- {1192, {wxRegion, contains_4, 4}},
- {1193, {wxRegion, contains_1_1, 1}},
- {1194, {wxRegion, convertToBitmap, 0}},
- {1195, {wxRegion, getBox, 0}},
- {1196, {wxRegion, intersect_4, 4}},
- {1197, {wxRegion, intersect_1_1, 1}},
- {1198, {wxRegion, intersect_1_0, 1}},
- {1199, {wxRegion, isEmpty, 0}},
- {1200, {wxRegion, subtract_4, 4}},
- {1201, {wxRegion, subtract_1_1, 1}},
- {1202, {wxRegion, subtract_1_0, 1}},
- {1203, {wxRegion, offset_2, 2}},
- {1204, {wxRegion, offset_1, 1}},
- {1205, {wxRegion, union_4, 4}},
- {1206, {wxRegion, union_1_2, 1}},
- {1207, {wxRegion, union_1_1, 1}},
- {1208, {wxRegion, union_1_0, 1}},
- {1209, {wxRegion, union_3, 3}},
- {1210, {wxRegion, xor_4, 4}},
- {1211, {wxRegion, xor_1_1, 1}},
- {1212, {wxRegion, xor_1_0, 1}},
- {1213, {wxAcceleratorTable, new_0, 0}},
- {1214, {wxAcceleratorTable, new_2, 2}},
- {1215, {wxAcceleratorTable, destruct, 0}},
- {1216, {wxAcceleratorTable, ok, 0}},
- {1217, {wxAcceleratorEntry, new_1_0, 1}},
- {1218, {wxAcceleratorEntry, new_1_1, 1}},
- {1219, {wxAcceleratorEntry, getCommand, 0}},
- {1220, {wxAcceleratorEntry, getFlags, 0}},
- {1221, {wxAcceleratorEntry, getKeyCode, 0}},
- {1222, {wxAcceleratorEntry, set, 4}},
- {1223, {wxAcceleratorEntry, 'Destroy', undefined}},
- {1228, {wxCaret, new_3, 3}},
- {1229, {wxCaret, new_2, 2}},
- {1231, {wxCaret, destruct, 0}},
- {1232, {wxCaret, create_3, 3}},
- {1233, {wxCaret, create_2, 2}},
- {1234, {wxCaret, getBlinkTime, 0}},
- {1236, {wxCaret, getPosition, 0}},
- {1238, {wxCaret, getSize, 0}},
- {1239, {wxCaret, getWindow, 0}},
- {1240, {wxCaret, hide, 0}},
- {1241, {wxCaret, isOk, 0}},
- {1242, {wxCaret, isVisible, 0}},
- {1243, {wxCaret, move_2, 2}},
- {1244, {wxCaret, move_1, 1}},
- {1245, {wxCaret, setBlinkTime, 1}},
- {1246, {wxCaret, setSize_2, 2}},
- {1247, {wxCaret, setSize_1, 1}},
- {1248, {wxCaret, show, 1}},
- {1249, {wxSizer, add_2_1, 2}},
- {1250, {wxSizer, add_2_0, 2}},
- {1251, {wxSizer, add_3, 3}},
- {1252, {wxSizer, add_2_3, 2}},
- {1253, {wxSizer, add_2_2, 2}},
- {1254, {wxSizer, addSpacer, 1}},
- {1255, {wxSizer, addStretchSpacer, 1}},
- {1256, {wxSizer, calcMin, 0}},
- {1257, {wxSizer, clear, 1}},
- {1258, {wxSizer, detach_1_2, 1}},
- {1259, {wxSizer, detach_1_1, 1}},
- {1260, {wxSizer, detach_1_0, 1}},
- {1261, {wxSizer, fit, 1}},
- {1262, {wxSizer, fitInside, 1}},
- {1263, {wxSizer, getChildren, 0}},
- {1264, {wxSizer, getItem_2_1, 2}},
- {1265, {wxSizer, getItem_2_0, 2}},
- {1266, {wxSizer, getItem_1, 1}},
- {1267, {wxSizer, getSize, 0}},
- {1268, {wxSizer, getPosition, 0}},
- {1269, {wxSizer, getMinSize, 0}},
- {1270, {wxSizer, hide_2_0, 2}},
- {1271, {wxSizer, hide_2_1, 2}},
- {1272, {wxSizer, hide_1, 1}},
- {1273, {wxSizer, insert_3_1, 3}},
- {1274, {wxSizer, insert_3_0, 3}},
- {1275, {wxSizer, insert_4, 4}},
- {1276, {wxSizer, insert_3_3, 3}},
- {1277, {wxSizer, insert_3_2, 3}},
- {1278, {wxSizer, insert_2, 2}},
- {1279, {wxSizer, insertSpacer, 2}},
- {1280, {wxSizer, insertStretchSpacer, 2}},
- {1281, {wxSizer, isShown_1_2, 1}},
- {1282, {wxSizer, isShown_1_1, 1}},
- {1283, {wxSizer, isShown_1_0, 1}},
- {1284, {wxSizer, layout, 0}},
- {1285, {wxSizer, prepend_2_1, 2}},
- {1286, {wxSizer, prepend_2_0, 2}},
- {1287, {wxSizer, prepend_3, 3}},
- {1288, {wxSizer, prepend_2_3, 2}},
- {1289, {wxSizer, prepend_2_2, 2}},
- {1290, {wxSizer, prepend_1, 1}},
- {1291, {wxSizer, prependSpacer, 1}},
- {1292, {wxSizer, prependStretchSpacer, 1}},
- {1293, {wxSizer, recalcSizes, 0}},
- {1294, {wxSizer, remove_1_1, 1}},
- {1295, {wxSizer, remove_1_0, 1}},
- {1296, {wxSizer, replace_3_1, 3}},
- {1297, {wxSizer, replace_3_0, 3}},
- {1298, {wxSizer, replace_2, 2}},
- {1299, {wxSizer, setDimension, 4}},
- {1300, {wxSizer, setMinSize_2, 2}},
- {1301, {wxSizer, setMinSize_1, 1}},
- {1302, {wxSizer, setItemMinSize_3_2, 3}},
- {1303, {wxSizer, setItemMinSize_2_2, 2}},
- {1304, {wxSizer, setItemMinSize_3_1, 3}},
- {1305, {wxSizer, setItemMinSize_2_1, 2}},
- {1306, {wxSizer, setItemMinSize_3_0, 3}},
- {1307, {wxSizer, setItemMinSize_2_0, 2}},
- {1308, {wxSizer, setSizeHints, 1}},
- {1309, {wxSizer, setVirtualSizeHints, 1}},
- {1310, {wxSizer, show_2_2, 2}},
- {1311, {wxSizer, show_2_1, 2}},
- {1312, {wxSizer, show_2_0, 2}},
- {1313, {wxSizer, show_1, 1}},
- {1314, {wxSizerFlags, new, 1}},
- {1315, {wxSizerFlags, align, 1}},
- {1316, {wxSizerFlags, border_2, 2}},
- {1317, {wxSizerFlags, border_1, 1}},
- {1318, {wxSizerFlags, center, 0}},
- {1319, {wxSizerFlags, centre, 0}},
- {1320, {wxSizerFlags, expand, 0}},
- {1321, {wxSizerFlags, left, 0}},
- {1322, {wxSizerFlags, proportion, 1}},
- {1323, {wxSizerFlags, right, 0}},
- {1324, {wxSizerFlags, 'Destroy', undefined}},
- {1325, {wxSizerItem, new_5_1, 5}},
- {1326, {wxSizerItem, new_2_1, 2}},
- {1327, {wxSizerItem, new_5_0, 5}},
- {1328, {wxSizerItem, new_2_0, 2}},
- {1329, {wxSizerItem, new_6, 6}},
- {1330, {wxSizerItem, new_3, 3}},
- {1331, {wxSizerItem, new_0, 0}},
- {1332, {wxSizerItem, destruct, 0}},
- {1333, {wxSizerItem, calcMin, 0}},
- {1334, {wxSizerItem, deleteWindows, 0}},
- {1335, {wxSizerItem, detachSizer, 0}},
- {1336, {wxSizerItem, getBorder, 0}},
- {1337, {wxSizerItem, getFlag, 0}},
- {1338, {wxSizerItem, getMinSize, 0}},
- {1339, {wxSizerItem, getPosition, 0}},
- {1340, {wxSizerItem, getProportion, 0}},
- {1341, {wxSizerItem, getRatio, 0}},
- {1342, {wxSizerItem, getRect, 0}},
- {1343, {wxSizerItem, getSize, 0}},
- {1344, {wxSizerItem, getSizer, 0}},
- {1345, {wxSizerItem, getSpacer, 0}},
- {1346, {wxSizerItem, getUserData, 0}},
- {1347, {wxSizerItem, getWindow, 0}},
- {1348, {wxSizerItem, isSizer, 0}},
- {1349, {wxSizerItem, isShown, 0}},
- {1350, {wxSizerItem, isSpacer, 0}},
- {1351, {wxSizerItem, isWindow, 0}},
- {1352, {wxSizerItem, setBorder, 1}},
- {1353, {wxSizerItem, setDimension, 2}},
- {1354, {wxSizerItem, setFlag, 1}},
- {1355, {wxSizerItem, setInitSize, 2}},
- {1356, {wxSizerItem, setMinSize_1, 1}},
- {1357, {wxSizerItem, setMinSize_2, 2}},
- {1358, {wxSizerItem, setProportion, 1}},
- {1359, {wxSizerItem, setRatio_2, 2}},
- {1360, {wxSizerItem, setRatio_1_1, 1}},
- {1361, {wxSizerItem, setRatio_1_0, 1}},
- {1362, {wxSizerItem, setSizer, 1}},
- {1363, {wxSizerItem, setSpacer_1, 1}},
- {1364, {wxSizerItem, setSpacer_2, 2}},
- {1365, {wxSizerItem, setWindow, 1}},
- {1366, {wxSizerItem, show, 1}},
- {1367, {wxBoxSizer, new, 1}},
- {1368, {wxBoxSizer, getOrientation, 0}},
- {1369, {wxBoxSizer, 'Destroy', undefined}},
- {1370, {wxStaticBoxSizer, new_2, 2}},
- {1371, {wxStaticBoxSizer, new_3, 3}},
- {1372, {wxStaticBoxSizer, getStaticBox, 0}},
- {1373, {wxStaticBoxSizer, 'Destroy', undefined}},
- {1374, {wxGridSizer, new_4, 4}},
- {1375, {wxGridSizer, new_2, 2}},
- {1376, {wxGridSizer, getCols, 0}},
- {1377, {wxGridSizer, getHGap, 0}},
- {1378, {wxGridSizer, getRows, 0}},
- {1379, {wxGridSizer, getVGap, 0}},
- {1380, {wxGridSizer, setCols, 1}},
- {1381, {wxGridSizer, setHGap, 1}},
- {1382, {wxGridSizer, setRows, 1}},
- {1383, {wxGridSizer, setVGap, 1}},
- {1384, {wxGridSizer, 'Destroy', undefined}},
- {1385, {wxFlexGridSizer, new_4, 4}},
- {1386, {wxFlexGridSizer, new_2, 2}},
- {1387, {wxFlexGridSizer, addGrowableCol, 2}},
- {1388, {wxFlexGridSizer, addGrowableRow, 2}},
- {1389, {wxFlexGridSizer, getFlexibleDirection, 0}},
- {1390, {wxFlexGridSizer, getNonFlexibleGrowMode, 0}},
- {1391, {wxFlexGridSizer, removeGrowableCol, 1}},
- {1392, {wxFlexGridSizer, removeGrowableRow, 1}},
- {1393, {wxFlexGridSizer, setFlexibleDirection, 1}},
- {1394, {wxFlexGridSizer, setNonFlexibleGrowMode, 1}},
- {1395, {wxFlexGridSizer, 'Destroy', undefined}},
- {1396, {wxGridBagSizer, new, 1}},
- {1397, {wxGridBagSizer, add_3_2, 3}},
- {1398, {wxGridBagSizer, add_3_1, 3}},
- {1399, {wxGridBagSizer, add_4, 4}},
- {1400, {wxGridBagSizer, add_1_0, 1}},
- {1401, {wxGridBagSizer, add_2_1, 2}},
- {1402, {wxGridBagSizer, add_2_0, 2}},
- {1403, {wxGridBagSizer, add_3_0, 3}},
- {1404, {wxGridBagSizer, add_1_1, 1}},
- {1405, {wxGridBagSizer, calcMin, 0}},
- {1406, {wxGridBagSizer, checkForIntersection_2, 2}},
- {1407, {wxGridBagSizer, checkForIntersection_3, 3}},
- {1408, {wxGridBagSizer, findItem_1_1, 1}},
- {1409, {wxGridBagSizer, findItem_1_0, 1}},
- {1410, {wxGridBagSizer, findItemAtPoint, 1}},
- {1411, {wxGridBagSizer, findItemAtPosition, 1}},
- {1412, {wxGridBagSizer, findItemWithData, 1}},
- {1413, {wxGridBagSizer, getCellSize, 2}},
- {1414, {wxGridBagSizer, getEmptyCellSize, 0}},
- {1415, {wxGridBagSizer, getItemPosition_1_2, 1}},
- {1416, {wxGridBagSizer, getItemPosition_1_1, 1}},
- {1417, {wxGridBagSizer, getItemPosition_1_0, 1}},
- {1418, {wxGridBagSizer, getItemSpan_1_2, 1}},
- {1419, {wxGridBagSizer, getItemSpan_1_1, 1}},
- {1420, {wxGridBagSizer, getItemSpan_1_0, 1}},
- {1421, {wxGridBagSizer, setEmptyCellSize, 1}},
- {1422, {wxGridBagSizer, setItemPosition_2_2, 2}},
- {1423, {wxGridBagSizer, setItemPosition_2_1, 2}},
- {1424, {wxGridBagSizer, setItemPosition_2_0, 2}},
- {1425, {wxGridBagSizer, setItemSpan_2_2, 2}},
- {1426, {wxGridBagSizer, setItemSpan_2_1, 2}},
- {1427, {wxGridBagSizer, setItemSpan_2_0, 2}},
- {1428, {wxGridBagSizer, 'Destroy', undefined}},
- {1429, {wxStdDialogButtonSizer, new, 0}},
- {1430, {wxStdDialogButtonSizer, addButton, 1}},
- {1431, {wxStdDialogButtonSizer, realize, 0}},
- {1432, {wxStdDialogButtonSizer, setAffirmativeButton, 1}},
- {1433, {wxStdDialogButtonSizer, setCancelButton, 1}},
- {1434, {wxStdDialogButtonSizer, setNegativeButton, 1}},
- {1435, {wxStdDialogButtonSizer, 'Destroy', undefined}},
- {1436, {wxFont, new_0, 0}},
- {1437, {wxFont, new_1, 1}},
- {1438, {wxFont, new_5, 5}},
- {1440, {wxFont, destruct, 0}},
- {1441, {wxFont, isFixedWidth, 0}},
- {1442, {wxFont, getDefaultEncoding, 0}},
- {1443, {wxFont, getFaceName, 0}},
- {1444, {wxFont, getFamily, 0}},
- {1445, {wxFont, getNativeFontInfoDesc, 0}},
- {1446, {wxFont, getNativeFontInfoUserDesc, 0}},
- {1447, {wxFont, getPointSize, 0}},
- {1448, {wxFont, getStyle, 0}},
- {1449, {wxFont, getUnderlined, 0}},
- {1450, {wxFont, getWeight, 0}},
- {1451, {wxFont, ok, 0}},
- {1452, {wxFont, setDefaultEncoding, 1}},
- {1453, {wxFont, setFaceName, 1}},
- {1454, {wxFont, setFamily, 1}},
- {1455, {wxFont, setPointSize, 1}},
- {1456, {wxFont, setStyle, 1}},
- {1457, {wxFont, setUnderlined, 1}},
- {1458, {wxFont, setWeight, 1}},
- {1459, {wxToolTip, enable, 1}},
- {1460, {wxToolTip, setDelay, 1}},
- {1461, {wxToolTip, new, 1}},
- {1462, {wxToolTip, setTip, 1}},
- {1463, {wxToolTip, getTip, 0}},
- {1464, {wxToolTip, getWindow, 0}},
- {1465, {wxToolTip, 'Destroy', undefined}},
- {1467, {wxButton, new_3, 3}},
- {1468, {wxButton, new_0, 0}},
- {1469, {wxButton, destruct, 0}},
- {1470, {wxButton, create, 3}},
- {1471, {wxButton, getDefaultSize, 0}},
- {1472, {wxButton, setDefault, 0}},
- {1473, {wxButton, setLabel, 1}},
- {1475, {wxBitmapButton, new_4, 4}},
- {1476, {wxBitmapButton, new_0, 0}},
- {1477, {wxBitmapButton, create, 4}},
- {1478, {wxBitmapButton, getBitmapDisabled, 0}},
- {1480, {wxBitmapButton, getBitmapFocus, 0}},
- {1482, {wxBitmapButton, getBitmapLabel, 0}},
- {1484, {wxBitmapButton, getBitmapSelected, 0}},
- {1486, {wxBitmapButton, setBitmapDisabled, 1}},
- {1487, {wxBitmapButton, setBitmapFocus, 1}},
- {1488, {wxBitmapButton, setBitmapLabel, 1}},
- {1489, {wxBitmapButton, setBitmapSelected, 1}},
- {1490, {wxBitmapButton, 'Destroy', undefined}},
- {1491, {wxToggleButton, new_0, 0}},
- {1492, {wxToggleButton, new_4, 4}},
- {1493, {wxToggleButton, create, 4}},
- {1494, {wxToggleButton, getValue, 0}},
- {1495, {wxToggleButton, setValue, 1}},
- {1496, {wxToggleButton, 'Destroy', undefined}},
- {1497, {wxCalendarCtrl, new_0, 0}},
- {1498, {wxCalendarCtrl, new_3, 3}},
- {1499, {wxCalendarCtrl, create, 3}},
- {1500, {wxCalendarCtrl, destruct, 0}},
- {1501, {wxCalendarCtrl, setDate, 1}},
- {1502, {wxCalendarCtrl, getDate, 0}},
- {1503, {wxCalendarCtrl, enableYearChange, 1}},
- {1504, {wxCalendarCtrl, enableMonthChange, 1}},
- {1505, {wxCalendarCtrl, enableHolidayDisplay, 1}},
- {1506, {wxCalendarCtrl, setHeaderColours, 2}},
- {1507, {wxCalendarCtrl, getHeaderColourFg, 0}},
- {1508, {wxCalendarCtrl, getHeaderColourBg, 0}},
- {1509, {wxCalendarCtrl, setHighlightColours, 2}},
- {1510, {wxCalendarCtrl, getHighlightColourFg, 0}},
- {1511, {wxCalendarCtrl, getHighlightColourBg, 0}},
- {1512, {wxCalendarCtrl, setHolidayColours, 2}},
- {1513, {wxCalendarCtrl, getHolidayColourFg, 0}},
- {1514, {wxCalendarCtrl, getHolidayColourBg, 0}},
- {1515, {wxCalendarCtrl, getAttr, 1}},
- {1516, {wxCalendarCtrl, setAttr, 2}},
- {1517, {wxCalendarCtrl, setHoliday, 1}},
- {1518, {wxCalendarCtrl, resetAttr, 1}},
- {1519, {wxCalendarCtrl, hitTest, 2}},
- {1520, {wxCalendarDateAttr, new_0, 0}},
- {1521, {wxCalendarDateAttr, new_2_1, 2}},
- {1522, {wxCalendarDateAttr, new_2_0, 2}},
- {1523, {wxCalendarDateAttr, setTextColour, 1}},
- {1524, {wxCalendarDateAttr, setBackgroundColour, 1}},
- {1525, {wxCalendarDateAttr, setBorderColour, 1}},
- {1526, {wxCalendarDateAttr, setFont, 1}},
- {1527, {wxCalendarDateAttr, setBorder, 1}},
- {1528, {wxCalendarDateAttr, setHoliday, 1}},
- {1529, {wxCalendarDateAttr, hasTextColour, 0}},
- {1530, {wxCalendarDateAttr, hasBackgroundColour, 0}},
- {1531, {wxCalendarDateAttr, hasBorderColour, 0}},
- {1532, {wxCalendarDateAttr, hasFont, 0}},
- {1533, {wxCalendarDateAttr, hasBorder, 0}},
- {1534, {wxCalendarDateAttr, isHoliday, 0}},
- {1535, {wxCalendarDateAttr, getTextColour, 0}},
- {1536, {wxCalendarDateAttr, getBackgroundColour, 0}},
- {1537, {wxCalendarDateAttr, getBorderColour, 0}},
- {1538, {wxCalendarDateAttr, getFont, 0}},
- {1539, {wxCalendarDateAttr, getBorder, 0}},
- {1540, {wxCalendarDateAttr, 'Destroy', undefined}},
- {1542, {wxCheckBox, new_4, 4}},
- {1543, {wxCheckBox, new_0, 0}},
- {1544, {wxCheckBox, create, 4}},
- {1545, {wxCheckBox, getValue, 0}},
- {1546, {wxCheckBox, get3StateValue, 0}},
- {1547, {wxCheckBox, is3rdStateAllowedForUser, 0}},
- {1548, {wxCheckBox, is3State, 0}},
- {1549, {wxCheckBox, isChecked, 0}},
- {1550, {wxCheckBox, setValue, 1}},
- {1551, {wxCheckBox, set3StateValue, 1}},
- {1552, {wxCheckBox, 'Destroy', undefined}},
- {1553, {wxCheckListBox, new_0, 0}},
- {1555, {wxCheckListBox, new_3, 3}},
- {1556, {wxCheckListBox, check, 2}},
- {1557, {wxCheckListBox, isChecked, 1}},
- {1558, {wxCheckListBox, 'Destroy', undefined}},
- {1561, {wxChoice, new_3, 3}},
- {1562, {wxChoice, new_0, 0}},
- {1564, {wxChoice, destruct, 0}},
- {1566, {wxChoice, create, 6}},
- {1567, {wxChoice, delete, 1}},
- {1568, {wxChoice, getColumns, 0}},
- {1569, {wxChoice, setColumns, 1}},
- {1570, {wxComboBox, new_0, 0}},
- {1572, {wxComboBox, new_3, 3}},
- {1573, {wxComboBox, destruct, 0}},
- {1575, {wxComboBox, create, 7}},
- {1576, {wxComboBox, canCopy, 0}},
- {1577, {wxComboBox, canCut, 0}},
- {1578, {wxComboBox, canPaste, 0}},
- {1579, {wxComboBox, canRedo, 0}},
- {1580, {wxComboBox, canUndo, 0}},
- {1581, {wxComboBox, copy, 0}},
- {1582, {wxComboBox, cut, 0}},
- {1583, {wxComboBox, getInsertionPoint, 0}},
- {1584, {wxComboBox, getLastPosition, 0}},
- {1585, {wxComboBox, getValue, 0}},
- {1586, {wxComboBox, paste, 0}},
- {1587, {wxComboBox, redo, 0}},
- {1588, {wxComboBox, replace, 3}},
- {1589, {wxComboBox, remove, 2}},
- {1590, {wxComboBox, setInsertionPoint, 1}},
- {1591, {wxComboBox, setInsertionPointEnd, 0}},
- {1592, {wxComboBox, setSelection_1, 1}},
- {1593, {wxComboBox, setSelection_2, 2}},
- {1594, {wxComboBox, setValue, 1}},
- {1595, {wxComboBox, undo, 0}},
- {1596, {wxGauge, new_0, 0}},
- {1597, {wxGauge, new_4, 4}},
- {1598, {wxGauge, create, 4}},
- {1599, {wxGauge, getBezelFace, 0}},
- {1600, {wxGauge, getRange, 0}},
- {1601, {wxGauge, getShadowWidth, 0}},
- {1602, {wxGauge, getValue, 0}},
- {1603, {wxGauge, isVertical, 0}},
- {1604, {wxGauge, setBezelFace, 1}},
- {1605, {wxGauge, setRange, 1}},
- {1606, {wxGauge, setShadowWidth, 1}},
- {1607, {wxGauge, setValue, 1}},
- {1608, {wxGauge, pulse, 0}},
- {1609, {wxGauge, 'Destroy', undefined}},
- {1610, {wxGenericDirCtrl, new_0, 0}},
- {1611, {wxGenericDirCtrl, new_2, 2}},
- {1612, {wxGenericDirCtrl, destruct, 0}},
- {1613, {wxGenericDirCtrl, create, 2}},
- {1614, {wxGenericDirCtrl, init, 0}},
- {1615, {wxGenericDirCtrl, collapseTree, 0}},
- {1616, {wxGenericDirCtrl, expandPath, 1}},
- {1617, {wxGenericDirCtrl, getDefaultPath, 0}},
- {1618, {wxGenericDirCtrl, getPath, 0}},
- {1619, {wxGenericDirCtrl, getFilePath, 0}},
- {1620, {wxGenericDirCtrl, getFilter, 0}},
- {1621, {wxGenericDirCtrl, getFilterIndex, 0}},
- {1622, {wxGenericDirCtrl, getRootId, 0}},
- {1623, {wxGenericDirCtrl, getTreeCtrl, 0}},
- {1624, {wxGenericDirCtrl, reCreateTree, 0}},
- {1625, {wxGenericDirCtrl, setDefaultPath, 1}},
- {1626, {wxGenericDirCtrl, setFilter, 1}},
- {1627, {wxGenericDirCtrl, setFilterIndex, 1}},
- {1628, {wxGenericDirCtrl, setPath, 1}},
- {1630, {wxStaticBox, new_4, 4}},
- {1631, {wxStaticBox, new_0, 0}},
- {1632, {wxStaticBox, create, 4}},
- {1633, {wxStaticBox, 'Destroy', undefined}},
- {1635, {wxStaticLine, new_2, 2}},
- {1636, {wxStaticLine, new_0, 0}},
- {1637, {wxStaticLine, create, 2}},
- {1638, {wxStaticLine, isVertical, 0}},
- {1639, {wxStaticLine, getDefaultSize, 0}},
- {1640, {wxStaticLine, 'Destroy', undefined}},
- {1643, {wxListBox, new_3, 3}},
- {1644, {wxListBox, new_0, 0}},
- {1646, {wxListBox, destruct, 0}},
- {1648, {wxListBox, create, 6}},
- {1649, {wxListBox, deselect, 1}},
- {1650, {wxListBox, getSelections, 1}},
- {1651, {wxListBox, insertItems, 2}},
- {1652, {wxListBox, isSelected, 1}},
- {1653, {wxListBox, set, 1}},
- {1654, {wxListBox, hitTest, 1}},
- {1655, {wxListBox, setFirstItem_1_0, 1}},
- {1656, {wxListBox, setFirstItem_1_1, 1}},
- {1657, {wxListCtrl, new_0, 0}},
- {1658, {wxListCtrl, new_2, 2}},
- {1659, {wxListCtrl, arrange, 1}},
- {1660, {wxListCtrl, assignImageList, 2}},
- {1661, {wxListCtrl, clearAll, 0}},
- {1662, {wxListCtrl, create, 2}},
- {1663, {wxListCtrl, deleteAllItems, 0}},
- {1664, {wxListCtrl, deleteColumn, 1}},
- {1665, {wxListCtrl, deleteItem, 1}},
- {1666, {wxListCtrl, editLabel, 1}},
- {1667, {wxListCtrl, ensureVisible, 1}},
- {1668, {wxListCtrl, findItem_3_0, 3}},
- {1669, {wxListCtrl, findItem_3_1, 3}},
- {1670, {wxListCtrl, getColumn, 2}},
- {1671, {wxListCtrl, getColumnCount, 0}},
- {1672, {wxListCtrl, getColumnWidth, 1}},
- {1673, {wxListCtrl, getCountPerPage, 0}},
- {1674, {wxListCtrl, getEditControl, 0}},
- {1675, {wxListCtrl, getImageList, 1}},
- {1676, {wxListCtrl, getItem, 1}},
- {1677, {wxListCtrl, getItemBackgroundColour, 1}},
- {1678, {wxListCtrl, getItemCount, 0}},
- {1679, {wxListCtrl, getItemData, 1}},
- {1680, {wxListCtrl, getItemFont, 1}},
- {1681, {wxListCtrl, getItemPosition, 2}},
- {1682, {wxListCtrl, getItemRect, 3}},
- {1683, {wxListCtrl, getItemSpacing, 0}},
- {1684, {wxListCtrl, getItemState, 2}},
- {1685, {wxListCtrl, getItemText, 1}},
- {1686, {wxListCtrl, getItemTextColour, 1}},
- {1687, {wxListCtrl, getNextItem, 2}},
- {1688, {wxListCtrl, getSelectedItemCount, 0}},
- {1689, {wxListCtrl, getTextColour, 0}},
- {1690, {wxListCtrl, getTopItem, 0}},
- {1691, {wxListCtrl, getViewRect, 0}},
- {1692, {wxListCtrl, hitTest, 2}},
- {1693, {wxListCtrl, insertColumn_2, 2}},
- {1694, {wxListCtrl, insertColumn_3, 3}},
- {1695, {wxListCtrl, insertItem_1, 1}},
- {1696, {wxListCtrl, insertItem_2_1, 2}},
- {1697, {wxListCtrl, insertItem_2_0, 2}},
- {1698, {wxListCtrl, insertItem_3, 3}},
- {1699, {wxListCtrl, refreshItem, 1}},
- {1700, {wxListCtrl, refreshItems, 2}},
- {1701, {wxListCtrl, scrollList, 2}},
- {1702, {wxListCtrl, setBackgroundColour, 1}},
- {1703, {wxListCtrl, setColumn, 2}},
- {1704, {wxListCtrl, setColumnWidth, 2}},
- {1705, {wxListCtrl, setImageList, 2}},
- {1706, {wxListCtrl, setItem_1, 1}},
- {1707, {wxListCtrl, setItem_4, 4}},
- {1708, {wxListCtrl, setItemBackgroundColour, 2}},
- {1709, {wxListCtrl, setItemCount, 1}},
- {1710, {wxListCtrl, setItemData, 2}},
- {1711, {wxListCtrl, setItemFont, 2}},
- {1712, {wxListCtrl, setItemImage, 3}},
- {1713, {wxListCtrl, setItemColumnImage, 3}},
- {1714, {wxListCtrl, setItemPosition, 2}},
- {1715, {wxListCtrl, setItemState, 3}},
- {1716, {wxListCtrl, setItemText, 2}},
- {1717, {wxListCtrl, setItemTextColour, 2}},
- {1718, {wxListCtrl, setSingleStyle, 2}},
- {1719, {wxListCtrl, setTextColour, 1}},
- {1720, {wxListCtrl, setWindowStyleFlag, 1}},
- {1721, {wxListCtrl, sortItems, 2}},
- {1722, {wxListCtrl, 'Destroy', undefined}},
- {1723, {wxListView, clearColumnImage, 1}},
- {1724, {wxListView, focus, 1}},
- {1725, {wxListView, getFirstSelected, 0}},
- {1726, {wxListView, getFocusedItem, 0}},
- {1727, {wxListView, getNextSelected, 1}},
- {1728, {wxListView, isSelected, 1}},
- {1729, {wxListView, select, 2}},
- {1730, {wxListView, setColumnImage, 2}},
- {1731, {wxListItem, new_0, 0}},
- {1732, {wxListItem, new_1, 1}},
- {1733, {wxListItem, destruct, 0}},
- {1734, {wxListItem, clear, 0}},
- {1735, {wxListItem, getAlign, 0}},
- {1736, {wxListItem, getBackgroundColour, 0}},
- {1737, {wxListItem, getColumn, 0}},
- {1738, {wxListItem, getFont, 0}},
- {1739, {wxListItem, getId, 0}},
- {1740, {wxListItem, getImage, 0}},
- {1741, {wxListItem, getMask, 0}},
- {1742, {wxListItem, getState, 0}},
- {1743, {wxListItem, getText, 0}},
- {1744, {wxListItem, getTextColour, 0}},
- {1745, {wxListItem, getWidth, 0}},
- {1746, {wxListItem, setAlign, 1}},
- {1747, {wxListItem, setBackgroundColour, 1}},
- {1748, {wxListItem, setColumn, 1}},
- {1749, {wxListItem, setFont, 1}},
- {1750, {wxListItem, setId, 1}},
- {1751, {wxListItem, setImage, 1}},
- {1752, {wxListItem, setMask, 1}},
- {1753, {wxListItem, setState, 1}},
- {1754, {wxListItem, setStateMask, 1}},
- {1755, {wxListItem, setText, 1}},
- {1756, {wxListItem, setTextColour, 1}},
- {1757, {wxListItem, setWidth, 1}},
- {1758, {wxListItemAttr, new_0, 0}},
- {1759, {wxListItemAttr, new_3, 3}},
- {1760, {wxListItemAttr, getBackgroundColour, 0}},
- {1761, {wxListItemAttr, getFont, 0}},
- {1762, {wxListItemAttr, getTextColour, 0}},
- {1763, {wxListItemAttr, hasBackgroundColour, 0}},
- {1764, {wxListItemAttr, hasFont, 0}},
- {1765, {wxListItemAttr, hasTextColour, 0}},
- {1766, {wxListItemAttr, setBackgroundColour, 1}},
- {1767, {wxListItemAttr, setFont, 1}},
- {1768, {wxListItemAttr, setTextColour, 1}},
- {1769, {wxListItemAttr, 'Destroy', undefined}},
- {1770, {wxImageList, new_0, 0}},
- {1771, {wxImageList, new_3, 3}},
- {1772, {wxImageList, add_1, 1}},
- {1773, {wxImageList, add_2_0, 2}},
- {1774, {wxImageList, add_2_1, 2}},
- {1775, {wxImageList, create, 3}},
- {1777, {wxImageList, draw, 5}},
- {1778, {wxImageList, getBitmap, 1}},
- {1779, {wxImageList, getIcon, 1}},
- {1780, {wxImageList, getImageCount, 0}},
- {1781, {wxImageList, getSize, 3}},
- {1782, {wxImageList, remove, 1}},
- {1783, {wxImageList, removeAll, 0}},
- {1784, {wxImageList, replace_2, 2}},
- {1785, {wxImageList, replace_3, 3}},
- {1786, {wxImageList, 'Destroy', undefined}},
- {1787, {wxTextAttr, new_0, 0}},
- {1788, {wxTextAttr, new_2, 2}},
- {1789, {wxTextAttr, getAlignment, 0}},
- {1790, {wxTextAttr, getBackgroundColour, 0}},
- {1791, {wxTextAttr, getFont, 0}},
- {1792, {wxTextAttr, getLeftIndent, 0}},
- {1793, {wxTextAttr, getLeftSubIndent, 0}},
- {1794, {wxTextAttr, getRightIndent, 0}},
- {1795, {wxTextAttr, getTabs, 0}},
- {1796, {wxTextAttr, getTextColour, 0}},
- {1797, {wxTextAttr, hasBackgroundColour, 0}},
- {1798, {wxTextAttr, hasFont, 0}},
- {1799, {wxTextAttr, hasTextColour, 0}},
- {1800, {wxTextAttr, getFlags, 0}},
- {1801, {wxTextAttr, isDefault, 0}},
- {1802, {wxTextAttr, setAlignment, 1}},
- {1803, {wxTextAttr, setBackgroundColour, 1}},
- {1804, {wxTextAttr, setFlags, 1}},
- {1805, {wxTextAttr, setFont, 2}},
- {1806, {wxTextAttr, setLeftIndent, 2}},
- {1807, {wxTextAttr, setRightIndent, 1}},
- {1808, {wxTextAttr, setTabs, 1}},
- {1809, {wxTextAttr, setTextColour, 1}},
- {1810, {wxTextAttr, 'Destroy', undefined}},
- {1812, {wxTextCtrl, new_3, 3}},
- {1813, {wxTextCtrl, new_0, 0}},
- {1815, {wxTextCtrl, destruct, 0}},
- {1816, {wxTextCtrl, appendText, 1}},
- {1817, {wxTextCtrl, canCopy, 0}},
- {1818, {wxTextCtrl, canCut, 0}},
- {1819, {wxTextCtrl, canPaste, 0}},
- {1820, {wxTextCtrl, canRedo, 0}},
- {1821, {wxTextCtrl, canUndo, 0}},
- {1822, {wxTextCtrl, clear, 0}},
- {1823, {wxTextCtrl, copy, 0}},
- {1824, {wxTextCtrl, create, 3}},
- {1825, {wxTextCtrl, cut, 0}},
- {1826, {wxTextCtrl, discardEdits, 0}},
- {1827, {wxTextCtrl, changeValue, 1}},
- {1828, {wxTextCtrl, emulateKeyPress, 1}},
- {1829, {wxTextCtrl, getDefaultStyle, 0}},
- {1830, {wxTextCtrl, getInsertionPoint, 0}},
- {1831, {wxTextCtrl, getLastPosition, 0}},
- {1832, {wxTextCtrl, getLineLength, 1}},
- {1833, {wxTextCtrl, getLineText, 1}},
- {1834, {wxTextCtrl, getNumberOfLines, 0}},
- {1835, {wxTextCtrl, getRange, 2}},
- {1836, {wxTextCtrl, getSelection, 2}},
- {1837, {wxTextCtrl, getStringSelection, 0}},
- {1838, {wxTextCtrl, getStyle, 2}},
- {1839, {wxTextCtrl, getValue, 0}},
- {1840, {wxTextCtrl, isEditable, 0}},
- {1841, {wxTextCtrl, isModified, 0}},
- {1842, {wxTextCtrl, isMultiLine, 0}},
- {1843, {wxTextCtrl, isSingleLine, 0}},
- {1844, {wxTextCtrl, loadFile, 2}},
- {1845, {wxTextCtrl, markDirty, 0}},
- {1846, {wxTextCtrl, paste, 0}},
- {1847, {wxTextCtrl, positionToXY, 3}},
- {1848, {wxTextCtrl, redo, 0}},
- {1849, {wxTextCtrl, remove, 2}},
- {1850, {wxTextCtrl, replace, 3}},
- {1851, {wxTextCtrl, saveFile, 1}},
- {1852, {wxTextCtrl, setDefaultStyle, 1}},
- {1853, {wxTextCtrl, setEditable, 1}},
- {1854, {wxTextCtrl, setInsertionPoint, 1}},
- {1855, {wxTextCtrl, setInsertionPointEnd, 0}},
- {1857, {wxTextCtrl, setMaxLength, 1}},
- {1858, {wxTextCtrl, setSelection, 2}},
- {1859, {wxTextCtrl, setStyle, 3}},
- {1860, {wxTextCtrl, setValue, 1}},
- {1861, {wxTextCtrl, showPosition, 1}},
- {1862, {wxTextCtrl, undo, 0}},
- {1863, {wxTextCtrl, writeText, 1}},
- {1864, {wxTextCtrl, xYToPosition, 2}},
- {1867, {wxNotebook, new_0, 0}},
- {1868, {wxNotebook, new_3, 3}},
- {1869, {wxNotebook, destruct, 0}},
- {1870, {wxNotebook, addPage, 3}},
- {1871, {wxNotebook, advanceSelection, 1}},
- {1872, {wxNotebook, assignImageList, 1}},
- {1873, {wxNotebook, create, 3}},
- {1874, {wxNotebook, deleteAllPages, 0}},
- {1875, {wxNotebook, deletePage, 1}},
- {1876, {wxNotebook, removePage, 1}},
- {1877, {wxNotebook, getCurrentPage, 0}},
- {1878, {wxNotebook, getImageList, 0}},
- {1880, {wxNotebook, getPage, 1}},
- {1881, {wxNotebook, getPageCount, 0}},
- {1882, {wxNotebook, getPageImage, 1}},
- {1883, {wxNotebook, getPageText, 1}},
- {1884, {wxNotebook, getRowCount, 0}},
- {1885, {wxNotebook, getSelection, 0}},
- {1886, {wxNotebook, getThemeBackgroundColour, 0}},
- {1888, {wxNotebook, hitTest, 2}},
- {1890, {wxNotebook, insertPage, 4}},
- {1891, {wxNotebook, setImageList, 1}},
- {1892, {wxNotebook, setPadding, 1}},
- {1893, {wxNotebook, setPageSize, 1}},
- {1894, {wxNotebook, setPageImage, 2}},
- {1895, {wxNotebook, setPageText, 2}},
- {1896, {wxNotebook, setSelection, 1}},
- {1897, {wxNotebook, changeSelection, 1}},
- {1898, {wxChoicebook, new_0, 0}},
- {1899, {wxChoicebook, new_3, 3}},
- {1900, {wxChoicebook, addPage, 3}},
- {1901, {wxChoicebook, advanceSelection, 1}},
- {1902, {wxChoicebook, assignImageList, 1}},
- {1903, {wxChoicebook, create, 3}},
- {1904, {wxChoicebook, deleteAllPages, 0}},
- {1905, {wxChoicebook, deletePage, 1}},
- {1906, {wxChoicebook, removePage, 1}},
- {1907, {wxChoicebook, getCurrentPage, 0}},
- {1908, {wxChoicebook, getImageList, 0}},
- {1910, {wxChoicebook, getPage, 1}},
- {1911, {wxChoicebook, getPageCount, 0}},
- {1912, {wxChoicebook, getPageImage, 1}},
- {1913, {wxChoicebook, getPageText, 1}},
- {1914, {wxChoicebook, getSelection, 0}},
- {1915, {wxChoicebook, hitTest, 2}},
- {1916, {wxChoicebook, insertPage, 4}},
- {1917, {wxChoicebook, setImageList, 1}},
- {1918, {wxChoicebook, setPageSize, 1}},
- {1919, {wxChoicebook, setPageImage, 2}},
- {1920, {wxChoicebook, setPageText, 2}},
- {1921, {wxChoicebook, setSelection, 1}},
- {1922, {wxChoicebook, changeSelection, 1}},
- {1923, {wxChoicebook, 'Destroy', undefined}},
- {1924, {wxToolbook, new_0, 0}},
- {1925, {wxToolbook, new_3, 3}},
- {1926, {wxToolbook, addPage, 3}},
- {1927, {wxToolbook, advanceSelection, 1}},
- {1928, {wxToolbook, assignImageList, 1}},
- {1929, {wxToolbook, create, 3}},
- {1930, {wxToolbook, deleteAllPages, 0}},
- {1931, {wxToolbook, deletePage, 1}},
- {1932, {wxToolbook, removePage, 1}},
- {1933, {wxToolbook, getCurrentPage, 0}},
- {1934, {wxToolbook, getImageList, 0}},
- {1936, {wxToolbook, getPage, 1}},
- {1937, {wxToolbook, getPageCount, 0}},
- {1938, {wxToolbook, getPageImage, 1}},
- {1939, {wxToolbook, getPageText, 1}},
- {1940, {wxToolbook, getSelection, 0}},
- {1942, {wxToolbook, hitTest, 2}},
- {1943, {wxToolbook, insertPage, 4}},
- {1944, {wxToolbook, setImageList, 1}},
- {1945, {wxToolbook, setPageSize, 1}},
- {1946, {wxToolbook, setPageImage, 2}},
- {1947, {wxToolbook, setPageText, 2}},
- {1948, {wxToolbook, setSelection, 1}},
- {1949, {wxToolbook, changeSelection, 1}},
- {1950, {wxToolbook, 'Destroy', undefined}},
- {1951, {wxListbook, new_0, 0}},
- {1952, {wxListbook, new_3, 3}},
- {1953, {wxListbook, addPage, 3}},
- {1954, {wxListbook, advanceSelection, 1}},
- {1955, {wxListbook, assignImageList, 1}},
- {1956, {wxListbook, create, 3}},
- {1957, {wxListbook, deleteAllPages, 0}},
- {1958, {wxListbook, deletePage, 1}},
- {1959, {wxListbook, removePage, 1}},
- {1960, {wxListbook, getCurrentPage, 0}},
- {1961, {wxListbook, getImageList, 0}},
- {1963, {wxListbook, getPage, 1}},
- {1964, {wxListbook, getPageCount, 0}},
- {1965, {wxListbook, getPageImage, 1}},
- {1966, {wxListbook, getPageText, 1}},
- {1967, {wxListbook, getSelection, 0}},
- {1969, {wxListbook, hitTest, 2}},
- {1970, {wxListbook, insertPage, 4}},
- {1971, {wxListbook, setImageList, 1}},
- {1972, {wxListbook, setPageSize, 1}},
- {1973, {wxListbook, setPageImage, 2}},
- {1974, {wxListbook, setPageText, 2}},
- {1975, {wxListbook, setSelection, 1}},
- {1976, {wxListbook, changeSelection, 1}},
- {1977, {wxListbook, 'Destroy', undefined}},
- {1978, {wxTreebook, new_0, 0}},
- {1979, {wxTreebook, new_3, 3}},
- {1980, {wxTreebook, addPage, 3}},
- {1981, {wxTreebook, advanceSelection, 1}},
- {1982, {wxTreebook, assignImageList, 1}},
- {1983, {wxTreebook, create, 3}},
- {1984, {wxTreebook, deleteAllPages, 0}},
- {1985, {wxTreebook, deletePage, 1}},
- {1986, {wxTreebook, removePage, 1}},
- {1987, {wxTreebook, getCurrentPage, 0}},
- {1988, {wxTreebook, getImageList, 0}},
- {1990, {wxTreebook, getPage, 1}},
- {1991, {wxTreebook, getPageCount, 0}},
- {1992, {wxTreebook, getPageImage, 1}},
- {1993, {wxTreebook, getPageText, 1}},
- {1994, {wxTreebook, getSelection, 0}},
- {1995, {wxTreebook, expandNode, 2}},
- {1996, {wxTreebook, isNodeExpanded, 1}},
- {1998, {wxTreebook, hitTest, 2}},
- {1999, {wxTreebook, insertPage, 4}},
- {2000, {wxTreebook, insertSubPage, 4}},
- {2001, {wxTreebook, setImageList, 1}},
- {2002, {wxTreebook, setPageSize, 1}},
- {2003, {wxTreebook, setPageImage, 2}},
- {2004, {wxTreebook, setPageText, 2}},
- {2005, {wxTreebook, setSelection, 1}},
- {2006, {wxTreebook, changeSelection, 1}},
- {2007, {wxTreebook, 'Destroy', undefined}},
- {2010, {wxTreeCtrl, new_2, 2}},
- {2011, {wxTreeCtrl, new_0, 0}},
- {2013, {wxTreeCtrl, destruct, 0}},
- {2014, {wxTreeCtrl, addRoot, 2}},
- {2015, {wxTreeCtrl, appendItem, 3}},
- {2016, {wxTreeCtrl, assignImageList, 1}},
- {2017, {wxTreeCtrl, assignStateImageList, 1}},
- {2018, {wxTreeCtrl, collapse, 1}},
- {2019, {wxTreeCtrl, collapseAndReset, 1}},
- {2020, {wxTreeCtrl, create, 2}},
- {2021, {wxTreeCtrl, delete, 1}},
- {2022, {wxTreeCtrl, deleteAllItems, 0}},
- {2023, {wxTreeCtrl, deleteChildren, 1}},
- {2024, {wxTreeCtrl, editLabel, 1}},
- {2025, {wxTreeCtrl, ensureVisible, 1}},
- {2026, {wxTreeCtrl, expand, 1}},
- {2027, {wxTreeCtrl, getBoundingRect, 3}},
- {2029, {wxTreeCtrl, getChildrenCount, 2}},
- {2030, {wxTreeCtrl, getCount, 0}},
- {2031, {wxTreeCtrl, getEditControl, 0}},
- {2032, {wxTreeCtrl, getFirstChild, 2}},
- {2033, {wxTreeCtrl, getNextChild, 2}},
- {2034, {wxTreeCtrl, getFirstVisibleItem, 0}},
- {2035, {wxTreeCtrl, getImageList, 0}},
- {2036, {wxTreeCtrl, getIndent, 0}},
- {2037, {wxTreeCtrl, getItemBackgroundColour, 1}},
- {2038, {wxTreeCtrl, getItemData, 1}},
- {2039, {wxTreeCtrl, getItemFont, 1}},
- {2040, {wxTreeCtrl, getItemImage_1, 1}},
- {2041, {wxTreeCtrl, getItemImage_2, 2}},
- {2042, {wxTreeCtrl, getItemText, 1}},
- {2043, {wxTreeCtrl, getItemTextColour, 1}},
- {2044, {wxTreeCtrl, getLastChild, 1}},
- {2045, {wxTreeCtrl, getNextSibling, 1}},
- {2046, {wxTreeCtrl, getNextVisible, 1}},
- {2047, {wxTreeCtrl, getItemParent, 1}},
- {2048, {wxTreeCtrl, getPrevSibling, 1}},
- {2049, {wxTreeCtrl, getPrevVisible, 1}},
- {2050, {wxTreeCtrl, getRootItem, 0}},
- {2051, {wxTreeCtrl, getSelection, 0}},
- {2052, {wxTreeCtrl, getSelections, 1}},
- {2053, {wxTreeCtrl, getStateImageList, 0}},
- {2054, {wxTreeCtrl, hitTest, 2}},
- {2056, {wxTreeCtrl, insertItem, 4}},
- {2057, {wxTreeCtrl, isBold, 1}},
- {2058, {wxTreeCtrl, isExpanded, 1}},
- {2059, {wxTreeCtrl, isSelected, 1}},
- {2060, {wxTreeCtrl, isVisible, 1}},
- {2061, {wxTreeCtrl, itemHasChildren, 1}},
- {2062, {wxTreeCtrl, isTreeItemIdOk, 1}},
- {2063, {wxTreeCtrl, prependItem, 3}},
- {2064, {wxTreeCtrl, scrollTo, 1}},
- {2065, {wxTreeCtrl, selectItem_1, 1}},
- {2066, {wxTreeCtrl, selectItem_2, 2}},
- {2067, {wxTreeCtrl, setIndent, 1}},
- {2068, {wxTreeCtrl, setImageList, 1}},
- {2069, {wxTreeCtrl, setItemBackgroundColour, 2}},
- {2070, {wxTreeCtrl, setItemBold, 2}},
- {2071, {wxTreeCtrl, setItemData, 2}},
- {2072, {wxTreeCtrl, setItemDropHighlight, 2}},
- {2073, {wxTreeCtrl, setItemFont, 2}},
- {2074, {wxTreeCtrl, setItemHasChildren, 2}},
- {2075, {wxTreeCtrl, setItemImage_2, 2}},
- {2076, {wxTreeCtrl, setItemImage_3, 3}},
- {2077, {wxTreeCtrl, setItemText, 2}},
- {2078, {wxTreeCtrl, setItemTextColour, 2}},
- {2079, {wxTreeCtrl, setStateImageList, 1}},
- {2080, {wxTreeCtrl, setWindowStyle, 1}},
- {2081, {wxTreeCtrl, sortChildren, 1}},
- {2082, {wxTreeCtrl, toggle, 1}},
- {2083, {wxTreeCtrl, toggleItemSelection, 1}},
- {2084, {wxTreeCtrl, unselect, 0}},
- {2085, {wxTreeCtrl, unselectAll, 0}},
- {2086, {wxTreeCtrl, unselectItem, 1}},
- {2087, {wxScrollBar, new_0, 0}},
- {2088, {wxScrollBar, new_3, 3}},
- {2089, {wxScrollBar, destruct, 0}},
- {2090, {wxScrollBar, create, 3}},
- {2091, {wxScrollBar, getRange, 0}},
- {2092, {wxScrollBar, getPageSize, 0}},
- {2093, {wxScrollBar, getThumbPosition, 0}},
- {2094, {wxScrollBar, getThumbSize, 0}},
- {2095, {wxScrollBar, setThumbPosition, 1}},
- {2096, {wxScrollBar, setScrollbar, 5}},
- {2098, {wxSpinButton, new_2, 2}},
- {2099, {wxSpinButton, new_0, 0}},
- {2100, {wxSpinButton, create, 2}},
- {2101, {wxSpinButton, getMax, 0}},
- {2102, {wxSpinButton, getMin, 0}},
- {2103, {wxSpinButton, getValue, 0}},
- {2104, {wxSpinButton, setRange, 2}},
- {2105, {wxSpinButton, setValue, 1}},
- {2106, {wxSpinButton, 'Destroy', undefined}},
- {2107, {wxSpinCtrl, new_0, 0}},
- {2108, {wxSpinCtrl, new_2, 2}},
- {2110, {wxSpinCtrl, create, 2}},
- {2113, {wxSpinCtrl, setValue_1_1, 1}},
- {2114, {wxSpinCtrl, setValue_1_0, 1}},
- {2116, {wxSpinCtrl, getValue, 0}},
- {2118, {wxSpinCtrl, setRange, 2}},
- {2119, {wxSpinCtrl, setSelection, 2}},
- {2121, {wxSpinCtrl, getMin, 0}},
- {2123, {wxSpinCtrl, getMax, 0}},
- {2124, {wxSpinCtrl, 'Destroy', undefined}},
- {2125, {wxStaticText, new_0, 0}},
- {2126, {wxStaticText, new_4, 4}},
- {2127, {wxStaticText, create, 4}},
- {2128, {wxStaticText, getLabel, 0}},
- {2129, {wxStaticText, setLabel, 1}},
- {2130, {wxStaticText, wrap, 1}},
- {2131, {wxStaticText, 'Destroy', undefined}},
- {2132, {wxStaticBitmap, new_0, 0}},
- {2133, {wxStaticBitmap, new_4, 4}},
- {2134, {wxStaticBitmap, create, 4}},
- {2135, {wxStaticBitmap, getBitmap, 0}},
- {2136, {wxStaticBitmap, setBitmap, 1}},
- {2137, {wxStaticBitmap, 'Destroy', undefined}},
- {2138, {wxRadioBox, new, 7}},
- {2140, {wxRadioBox, destruct, 0}},
- {2141, {wxRadioBox, create, 7}},
- {2142, {wxRadioBox, enable_2, 2}},
- {2143, {wxRadioBox, enable_1, 1}},
- {2144, {wxRadioBox, getSelection, 0}},
- {2145, {wxRadioBox, getString, 1}},
- {2146, {wxRadioBox, setSelection, 1}},
- {2147, {wxRadioBox, show_2, 2}},
- {2148, {wxRadioBox, show_1, 1}},
- {2149, {wxRadioBox, getColumnCount, 0}},
- {2150, {wxRadioBox, getItemHelpText, 1}},
- {2151, {wxRadioBox, getItemToolTip, 1}},
- {2153, {wxRadioBox, getItemFromPoint, 1}},
- {2154, {wxRadioBox, getRowCount, 0}},
- {2155, {wxRadioBox, isItemEnabled, 1}},
- {2156, {wxRadioBox, isItemShown, 1}},
- {2157, {wxRadioBox, setItemHelpText, 2}},
- {2158, {wxRadioBox, setItemToolTip, 2}},
- {2159, {wxRadioButton, new_0, 0}},
- {2160, {wxRadioButton, new_4, 4}},
- {2161, {wxRadioButton, create, 4}},
- {2162, {wxRadioButton, getValue, 0}},
- {2163, {wxRadioButton, setValue, 1}},
- {2164, {wxRadioButton, 'Destroy', undefined}},
- {2166, {wxSlider, new_6, 6}},
- {2167, {wxSlider, new_0, 0}},
- {2168, {wxSlider, create, 6}},
- {2169, {wxSlider, getLineSize, 0}},
- {2170, {wxSlider, getMax, 0}},
- {2171, {wxSlider, getMin, 0}},
- {2172, {wxSlider, getPageSize, 0}},
- {2173, {wxSlider, getThumbLength, 0}},
- {2174, {wxSlider, getValue, 0}},
- {2175, {wxSlider, setLineSize, 1}},
- {2176, {wxSlider, setPageSize, 1}},
- {2177, {wxSlider, setRange, 2}},
- {2178, {wxSlider, setThumbLength, 1}},
- {2179, {wxSlider, setValue, 1}},
- {2180, {wxSlider, 'Destroy', undefined}},
- {2182, {wxDialog, new_4, 4}},
- {2183, {wxDialog, new_0, 0}},
- {2185, {wxDialog, destruct, 0}},
- {2186, {wxDialog, create, 4}},
- {2187, {wxDialog, createButtonSizer, 1}},
- {2188, {wxDialog, createStdDialogButtonSizer, 1}},
- {2189, {wxDialog, endModal, 1}},
- {2190, {wxDialog, getAffirmativeId, 0}},
- {2191, {wxDialog, getReturnCode, 0}},
- {2192, {wxDialog, isModal, 0}},
- {2193, {wxDialog, setAffirmativeId, 1}},
- {2194, {wxDialog, setReturnCode, 1}},
- {2195, {wxDialog, show, 1}},
- {2196, {wxDialog, showModal, 0}},
- {2197, {wxColourDialog, new_0, 0}},
- {2198, {wxColourDialog, new_2, 2}},
- {2199, {wxColourDialog, destruct, 0}},
- {2200, {wxColourDialog, create, 2}},
- {2201, {wxColourDialog, getColourData, 0}},
- {2202, {wxColourData, new_0, 0}},
- {2203, {wxColourData, new_1, 1}},
- {2204, {wxColourData, destruct, 0}},
- {2205, {wxColourData, getChooseFull, 0}},
- {2206, {wxColourData, getColour, 0}},
- {2208, {wxColourData, getCustomColour, 1}},
- {2209, {wxColourData, setChooseFull, 1}},
- {2210, {wxColourData, setColour, 1}},
- {2211, {wxColourData, setCustomColour, 2}},
- {2212, {wxPalette, new_0, 0}},
- {2213, {wxPalette, new_4, 4}},
- {2215, {wxPalette, destruct, 0}},
- {2216, {wxPalette, create, 4}},
- {2217, {wxPalette, getColoursCount, 0}},
- {2218, {wxPalette, getPixel, 3}},
- {2219, {wxPalette, getRGB, 4}},
- {2220, {wxPalette, isOk, 0}},
- {2224, {wxDirDialog, new, 2}},
- {2225, {wxDirDialog, destruct, 0}},
- {2226, {wxDirDialog, getPath, 0}},
- {2227, {wxDirDialog, getMessage, 0}},
- {2228, {wxDirDialog, setMessage, 1}},
- {2229, {wxDirDialog, setPath, 1}},
- {2233, {wxFileDialog, new, 2}},
- {2234, {wxFileDialog, destruct, 0}},
- {2235, {wxFileDialog, getDirectory, 0}},
- {2236, {wxFileDialog, getFilename, 0}},
- {2237, {wxFileDialog, getFilenames, 1}},
- {2238, {wxFileDialog, getFilterIndex, 0}},
- {2239, {wxFileDialog, getMessage, 0}},
- {2240, {wxFileDialog, getPath, 0}},
- {2241, {wxFileDialog, getPaths, 1}},
- {2242, {wxFileDialog, getWildcard, 0}},
- {2243, {wxFileDialog, setDirectory, 1}},
- {2244, {wxFileDialog, setFilename, 1}},
- {2245, {wxFileDialog, setFilterIndex, 1}},
- {2246, {wxFileDialog, setMessage, 1}},
- {2247, {wxFileDialog, setPath, 1}},
- {2248, {wxFileDialog, setWildcard, 1}},
- {2249, {wxPickerBase, setInternalMargin, 1}},
- {2250, {wxPickerBase, getInternalMargin, 0}},
- {2251, {wxPickerBase, setTextCtrlProportion, 1}},
- {2252, {wxPickerBase, setPickerCtrlProportion, 1}},
- {2253, {wxPickerBase, getTextCtrlProportion, 0}},
- {2254, {wxPickerBase, getPickerCtrlProportion, 0}},
- {2255, {wxPickerBase, hasTextCtrl, 0}},
- {2256, {wxPickerBase, getTextCtrl, 0}},
- {2257, {wxPickerBase, isTextCtrlGrowable, 0}},
- {2258, {wxPickerBase, setPickerCtrlGrowable, 1}},
- {2259, {wxPickerBase, setTextCtrlGrowable, 1}},
- {2260, {wxPickerBase, isPickerCtrlGrowable, 0}},
- {2261, {wxFilePickerCtrl, new_0, 0}},
- {2262, {wxFilePickerCtrl, new_3, 3}},
- {2263, {wxFilePickerCtrl, create, 3}},
- {2264, {wxFilePickerCtrl, getPath, 0}},
- {2265, {wxFilePickerCtrl, setPath, 1}},
- {2266, {wxFilePickerCtrl, 'Destroy', undefined}},
- {2267, {wxDirPickerCtrl, new_0, 0}},
- {2268, {wxDirPickerCtrl, new_3, 3}},
- {2269, {wxDirPickerCtrl, create, 3}},
- {2270, {wxDirPickerCtrl, getPath, 0}},
- {2271, {wxDirPickerCtrl, setPath, 1}},
- {2272, {wxDirPickerCtrl, 'Destroy', undefined}},
- {2273, {wxColourPickerCtrl, new_0, 0}},
- {2274, {wxColourPickerCtrl, new_3, 3}},
- {2275, {wxColourPickerCtrl, create, 3}},
- {2276, {wxColourPickerCtrl, getColour, 0}},
- {2277, {wxColourPickerCtrl, setColour_1_1, 1}},
- {2278, {wxColourPickerCtrl, setColour_1_0, 1}},
- {2279, {wxColourPickerCtrl, 'Destroy', undefined}},
- {2280, {wxDatePickerCtrl, new_0, 0}},
- {2281, {wxDatePickerCtrl, new_3, 3}},
- {2282, {wxDatePickerCtrl, getRange, 2}},
- {2283, {wxDatePickerCtrl, getValue, 0}},
- {2284, {wxDatePickerCtrl, setRange, 2}},
- {2285, {wxDatePickerCtrl, setValue, 1}},
- {2286, {wxDatePickerCtrl, 'Destroy', undefined}},
- {2287, {wxFontPickerCtrl, new_0, 0}},
- {2288, {wxFontPickerCtrl, new_3, 3}},
- {2289, {wxFontPickerCtrl, create, 3}},
- {2290, {wxFontPickerCtrl, getSelectedFont, 0}},
- {2291, {wxFontPickerCtrl, setSelectedFont, 1}},
- {2292, {wxFontPickerCtrl, getMaxPointSize, 0}},
- {2293, {wxFontPickerCtrl, setMaxPointSize, 1}},
- {2294, {wxFontPickerCtrl, 'Destroy', undefined}},
- {2297, {wxFindReplaceDialog, new_0, 0}},
- {2298, {wxFindReplaceDialog, new_4, 4}},
- {2299, {wxFindReplaceDialog, destruct, 0}},
- {2300, {wxFindReplaceDialog, create, 4}},
- {2301, {wxFindReplaceDialog, getData, 0}},
- {2302, {wxFindReplaceData, new_0, 0}},
- {2303, {wxFindReplaceData, new_1, 1}},
- {2304, {wxFindReplaceData, getFindString, 0}},
- {2305, {wxFindReplaceData, getReplaceString, 0}},
- {2306, {wxFindReplaceData, getFlags, 0}},
- {2307, {wxFindReplaceData, setFlags, 1}},
- {2308, {wxFindReplaceData, setFindString, 1}},
- {2309, {wxFindReplaceData, setReplaceString, 1}},
- {2310, {wxFindReplaceData, 'Destroy', undefined}},
- {2311, {wxMultiChoiceDialog, new_0, 0}},
- {2313, {wxMultiChoiceDialog, new_5, 5}},
- {2314, {wxMultiChoiceDialog, getSelections, 0}},
- {2315, {wxMultiChoiceDialog, setSelections, 1}},
- {2316, {wxMultiChoiceDialog, 'Destroy', undefined}},
- {2317, {wxSingleChoiceDialog, new_0, 0}},
- {2319, {wxSingleChoiceDialog, new_5, 5}},
- {2320, {wxSingleChoiceDialog, getSelection, 0}},
- {2321, {wxSingleChoiceDialog, getStringSelection, 0}},
- {2322, {wxSingleChoiceDialog, setSelection, 1}},
- {2323, {wxSingleChoiceDialog, 'Destroy', undefined}},
- {2324, {wxTextEntryDialog, new, 3}},
- {2325, {wxTextEntryDialog, getValue, 0}},
- {2326, {wxTextEntryDialog, setValue, 1}},
- {2327, {wxTextEntryDialog, 'Destroy', undefined}},
- {2328, {wxPasswordEntryDialog, new, 3}},
- {2329, {wxPasswordEntryDialog, 'Destroy', undefined}},
- {2330, {wxFontData, new_0, 0}},
- {2331, {wxFontData, new_1, 1}},
- {2332, {wxFontData, destruct, 0}},
- {2333, {wxFontData, enableEffects, 1}},
- {2334, {wxFontData, getAllowSymbols, 0}},
- {2335, {wxFontData, getColour, 0}},
- {2336, {wxFontData, getChosenFont, 0}},
- {2337, {wxFontData, getEnableEffects, 0}},
- {2338, {wxFontData, getInitialFont, 0}},
- {2339, {wxFontData, getShowHelp, 0}},
- {2340, {wxFontData, setAllowSymbols, 1}},
- {2341, {wxFontData, setChosenFont, 1}},
- {2342, {wxFontData, setColour, 1}},
- {2343, {wxFontData, setInitialFont, 1}},
- {2344, {wxFontData, setRange, 2}},
- {2345, {wxFontData, setShowHelp, 1}},
- {2349, {wxFontDialog, new_0, 0}},
- {2351, {wxFontDialog, new_2, 2}},
- {2353, {wxFontDialog, create, 2}},
- {2354, {wxFontDialog, getFontData, 0}},
- {2356, {wxFontDialog, 'Destroy', undefined}},
- {2357, {wxProgressDialog, new, 3}},
- {2358, {wxProgressDialog, destruct, 0}},
- {2359, {wxProgressDialog, resume, 0}},
- {2360, {wxProgressDialog, update_2, 2}},
- {2361, {wxProgressDialog, update_0, 0}},
- {2362, {wxMessageDialog, new, 3}},
- {2363, {wxMessageDialog, destruct, 0}},
- {2364, {wxPageSetupDialog, new, 2}},
- {2365, {wxPageSetupDialog, destruct, 0}},
- {2366, {wxPageSetupDialog, getPageSetupData, 0}},
- {2367, {wxPageSetupDialog, showModal, 0}},
- {2368, {wxPageSetupDialogData, new_0, 0}},
- {2369, {wxPageSetupDialogData, new_1_0, 1}},
- {2370, {wxPageSetupDialogData, new_1_1, 1}},
- {2371, {wxPageSetupDialogData, destruct, 0}},
- {2372, {wxPageSetupDialogData, enableHelp, 1}},
- {2373, {wxPageSetupDialogData, enableMargins, 1}},
- {2374, {wxPageSetupDialogData, enableOrientation, 1}},
- {2375, {wxPageSetupDialogData, enablePaper, 1}},
- {2376, {wxPageSetupDialogData, enablePrinter, 1}},
- {2377, {wxPageSetupDialogData, getDefaultMinMargins, 0}},
- {2378, {wxPageSetupDialogData, getEnableMargins, 0}},
- {2379, {wxPageSetupDialogData, getEnableOrientation, 0}},
- {2380, {wxPageSetupDialogData, getEnablePaper, 0}},
- {2381, {wxPageSetupDialogData, getEnablePrinter, 0}},
- {2382, {wxPageSetupDialogData, getEnableHelp, 0}},
- {2383, {wxPageSetupDialogData, getDefaultInfo, 0}},
- {2384, {wxPageSetupDialogData, getMarginTopLeft, 0}},
- {2385, {wxPageSetupDialogData, getMarginBottomRight, 0}},
- {2386, {wxPageSetupDialogData, getMinMarginTopLeft, 0}},
- {2387, {wxPageSetupDialogData, getMinMarginBottomRight, 0}},
- {2388, {wxPageSetupDialogData, getPaperId, 0}},
- {2389, {wxPageSetupDialogData, getPaperSize, 0}},
- {2391, {wxPageSetupDialogData, getPrintData, 0}},
- {2392, {wxPageSetupDialogData, isOk, 0}},
- {2393, {wxPageSetupDialogData, setDefaultInfo, 1}},
- {2394, {wxPageSetupDialogData, setDefaultMinMargins, 1}},
- {2395, {wxPageSetupDialogData, setMarginTopLeft, 1}},
- {2396, {wxPageSetupDialogData, setMarginBottomRight, 1}},
- {2397, {wxPageSetupDialogData, setMinMarginTopLeft, 1}},
- {2398, {wxPageSetupDialogData, setMinMarginBottomRight, 1}},
- {2399, {wxPageSetupDialogData, setPaperId, 1}},
- {2400, {wxPageSetupDialogData, setPaperSize_1_1, 1}},
- {2401, {wxPageSetupDialogData, setPaperSize_1_0, 1}},
- {2402, {wxPageSetupDialogData, setPrintData, 1}},
- {2403, {wxPrintDialog, new_2_0, 2}},
- {2404, {wxPrintDialog, new_2_1, 2}},
- {2405, {wxPrintDialog, destruct, 0}},
- {2406, {wxPrintDialog, getPrintDialogData, 0}},
- {2407, {wxPrintDialog, getPrintDC, 0}},
- {2408, {wxPrintDialogData, new_0, 0}},
- {2409, {wxPrintDialogData, new_1_1, 1}},
- {2410, {wxPrintDialogData, new_1_0, 1}},
- {2411, {wxPrintDialogData, destruct, 0}},
- {2412, {wxPrintDialogData, enableHelp, 1}},
- {2413, {wxPrintDialogData, enablePageNumbers, 1}},
- {2414, {wxPrintDialogData, enablePrintToFile, 1}},
- {2415, {wxPrintDialogData, enableSelection, 1}},
- {2416, {wxPrintDialogData, getAllPages, 0}},
- {2417, {wxPrintDialogData, getCollate, 0}},
- {2418, {wxPrintDialogData, getFromPage, 0}},
- {2419, {wxPrintDialogData, getMaxPage, 0}},
- {2420, {wxPrintDialogData, getMinPage, 0}},
- {2421, {wxPrintDialogData, getNoCopies, 0}},
- {2422, {wxPrintDialogData, getPrintData, 0}},
- {2423, {wxPrintDialogData, getPrintToFile, 0}},
- {2424, {wxPrintDialogData, getSelection, 0}},
- {2425, {wxPrintDialogData, getToPage, 0}},
- {2426, {wxPrintDialogData, isOk, 0}},
- {2427, {wxPrintDialogData, setCollate, 1}},
- {2428, {wxPrintDialogData, setFromPage, 1}},
- {2429, {wxPrintDialogData, setMaxPage, 1}},
- {2430, {wxPrintDialogData, setMinPage, 1}},
- {2431, {wxPrintDialogData, setNoCopies, 1}},
- {2432, {wxPrintDialogData, setPrintData, 1}},
- {2433, {wxPrintDialogData, setPrintToFile, 1}},
- {2434, {wxPrintDialogData, setSelection, 1}},
- {2435, {wxPrintDialogData, setToPage, 1}},
- {2436, {wxPrintData, new_0, 0}},
- {2437, {wxPrintData, new_1, 1}},
- {2438, {wxPrintData, destruct, 0}},
- {2439, {wxPrintData, getCollate, 0}},
- {2440, {wxPrintData, getBin, 0}},
- {2441, {wxPrintData, getColour, 0}},
- {2442, {wxPrintData, getDuplex, 0}},
- {2443, {wxPrintData, getNoCopies, 0}},
- {2444, {wxPrintData, getOrientation, 0}},
- {2445, {wxPrintData, getPaperId, 0}},
- {2446, {wxPrintData, getPrinterName, 0}},
- {2447, {wxPrintData, getQuality, 0}},
- {2448, {wxPrintData, isOk, 0}},
- {2449, {wxPrintData, setBin, 1}},
- {2450, {wxPrintData, setCollate, 1}},
- {2451, {wxPrintData, setColour, 1}},
- {2452, {wxPrintData, setDuplex, 1}},
- {2453, {wxPrintData, setNoCopies, 1}},
- {2454, {wxPrintData, setOrientation, 1}},
- {2455, {wxPrintData, setPaperId, 1}},
- {2456, {wxPrintData, setPrinterName, 1}},
- {2457, {wxPrintData, setQuality, 1}},
- {2460, {wxPrintPreview, new_2, 2}},
- {2461, {wxPrintPreview, new_3, 3}},
- {2463, {wxPrintPreview, destruct, 0}},
- {2464, {wxPrintPreview, getCanvas, 0}},
- {2465, {wxPrintPreview, getCurrentPage, 0}},
- {2466, {wxPrintPreview, getFrame, 0}},
- {2467, {wxPrintPreview, getMaxPage, 0}},
- {2468, {wxPrintPreview, getMinPage, 0}},
- {2469, {wxPrintPreview, getPrintout, 0}},
- {2470, {wxPrintPreview, getPrintoutForPrinting, 0}},
- {2471, {wxPrintPreview, isOk, 0}},
- {2472, {wxPrintPreview, paintPage, 2}},
- {2473, {wxPrintPreview, print, 1}},
- {2474, {wxPrintPreview, renderPage, 1}},
- {2475, {wxPrintPreview, setCanvas, 1}},
- {2476, {wxPrintPreview, setCurrentPage, 1}},
- {2477, {wxPrintPreview, setFrame, 1}},
- {2478, {wxPrintPreview, setPrintout, 1}},
- {2479, {wxPrintPreview, setZoom, 1}},
- {2480, {wxPreviewFrame, new, 3}},
- {2481, {wxPreviewFrame, destruct, 0}},
- {2482, {wxPreviewFrame, createControlBar, 0}},
- {2483, {wxPreviewFrame, createCanvas, 0}},
- {2484, {wxPreviewFrame, initialize, 0}},
- {2485, {wxPreviewFrame, onCloseWindow, 1}},
- {2486, {wxPreviewControlBar, new, 4}},
- {2487, {wxPreviewControlBar, destruct, 0}},
- {2488, {wxPreviewControlBar, createButtons, 0}},
- {2489, {wxPreviewControlBar, getPrintPreview, 0}},
- {2490, {wxPreviewControlBar, getZoomControl, 0}},
- {2491, {wxPreviewControlBar, setZoomControl, 1}},
- {2493, {wxPrinter, new, 1}},
- {2494, {wxPrinter, createAbortWindow, 2}},
- {2495, {wxPrinter, getAbort, 0}},
- {2496, {wxPrinter, getLastError, 0}},
- {2497, {wxPrinter, getPrintDialogData, 0}},
- {2498, {wxPrinter, print, 3}},
- {2499, {wxPrinter, printDialog, 1}},
- {2500, {wxPrinter, reportError, 3}},
- {2501, {wxPrinter, setup, 1}},
- {2502, {wxPrinter, 'Destroy', undefined}},
- {2503, {wxXmlResource, new_1, 1}},
- {2504, {wxXmlResource, new_2, 2}},
- {2505, {wxXmlResource, destruct, 0}},
- {2506, {wxXmlResource, attachUnknownControl, 3}},
- {2507, {wxXmlResource, clearHandlers, 0}},
- {2508, {wxXmlResource, compareVersion, 4}},
- {2509, {wxXmlResource, get, 0}},
- {2510, {wxXmlResource, getFlags, 0}},
- {2511, {wxXmlResource, getVersion, 0}},
- {2512, {wxXmlResource, getXRCID, 2}},
- {2513, {wxXmlResource, initAllHandlers, 0}},
- {2514, {wxXmlResource, load, 1}},
- {2515, {wxXmlResource, loadBitmap, 1}},
- {2516, {wxXmlResource, loadDialog_2, 2}},
- {2517, {wxXmlResource, loadDialog_3, 3}},
- {2518, {wxXmlResource, loadFrame_2, 2}},
- {2519, {wxXmlResource, loadFrame_3, 3}},
- {2520, {wxXmlResource, loadIcon, 1}},
- {2521, {wxXmlResource, loadMenu, 1}},
- {2522, {wxXmlResource, loadMenuBar_2, 2}},
- {2523, {wxXmlResource, loadMenuBar_1, 1}},
- {2524, {wxXmlResource, loadPanel_2, 2}},
- {2525, {wxXmlResource, loadPanel_3, 3}},
- {2526, {wxXmlResource, loadToolBar, 2}},
- {2527, {wxXmlResource, set, 1}},
- {2528, {wxXmlResource, setFlags, 1}},
- {2529, {wxXmlResource, unload, 1}},
- {2530, {wxXmlResource, xrcctrl, 3}},
- {2531, {wxHtmlEasyPrinting, new, 1}},
- {2532, {wxHtmlEasyPrinting, destruct, 0}},
- {2533, {wxHtmlEasyPrinting, getPrintData, 0}},
- {2534, {wxHtmlEasyPrinting, getPageSetupData, 0}},
- {2535, {wxHtmlEasyPrinting, previewFile, 1}},
- {2536, {wxHtmlEasyPrinting, previewText, 2}},
- {2537, {wxHtmlEasyPrinting, printFile, 1}},
- {2538, {wxHtmlEasyPrinting, printText, 2}},
- {2539, {wxHtmlEasyPrinting, pageSetup, 0}},
- {2540, {wxHtmlEasyPrinting, setFonts, 3}},
- {2541, {wxHtmlEasyPrinting, setHeader, 2}},
- {2542, {wxHtmlEasyPrinting, setFooter, 2}},
- {2544, {wxGLCanvas, new_2, 2}},
- {2545, {wxGLCanvas, new_3_1, 3}},
- {2546, {wxGLCanvas, new_3_0, 3}},
- {2547, {wxGLCanvas, getContext, 0}},
- {2549, {wxGLCanvas, setCurrent, 0}},
- {2550, {wxGLCanvas, swapBuffers, 0}},
- {2551, {wxGLCanvas, 'Destroy', undefined}},
- {2552, {wxAuiManager, new, 1}},
- {2553, {wxAuiManager, destruct, 0}},
- {2554, {wxAuiManager, addPane_2_1, 2}},
- {2555, {wxAuiManager, addPane_3, 3}},
- {2556, {wxAuiManager, addPane_2_0, 2}},
- {2557, {wxAuiManager, detachPane, 1}},
- {2558, {wxAuiManager, getAllPanes, 0}},
- {2559, {wxAuiManager, getArtProvider, 0}},
- {2560, {wxAuiManager, getDockSizeConstraint, 2}},
- {2561, {wxAuiManager, getFlags, 0}},
- {2562, {wxAuiManager, getManagedWindow, 0}},
- {2563, {wxAuiManager, getManager, 1}},
- {2564, {wxAuiManager, getPane_1_1, 1}},
- {2565, {wxAuiManager, getPane_1_0, 1}},
- {2566, {wxAuiManager, hideHint, 0}},
- {2567, {wxAuiManager, insertPane, 3}},
- {2568, {wxAuiManager, loadPaneInfo, 2}},
- {2569, {wxAuiManager, loadPerspective, 2}},
- {2570, {wxAuiManager, savePaneInfo, 1}},
- {2571, {wxAuiManager, savePerspective, 0}},
- {2572, {wxAuiManager, setArtProvider, 1}},
- {2573, {wxAuiManager, setDockSizeConstraint, 2}},
- {2574, {wxAuiManager, setFlags, 1}},
- {2575, {wxAuiManager, setManagedWindow, 1}},
- {2576, {wxAuiManager, showHint, 1}},
- {2577, {wxAuiManager, unInit, 0}},
- {2578, {wxAuiManager, update, 0}},
- {2579, {wxAuiPaneInfo, new_0, 0}},
- {2580, {wxAuiPaneInfo, new_1, 1}},
- {2581, {wxAuiPaneInfo, destruct, 0}},
- {2582, {wxAuiPaneInfo, bestSize_1, 1}},
- {2583, {wxAuiPaneInfo, bestSize_2, 2}},
- {2584, {wxAuiPaneInfo, bottom, 0}},
- {2585, {wxAuiPaneInfo, bottomDockable, 1}},
- {2586, {wxAuiPaneInfo, caption, 1}},
- {2587, {wxAuiPaneInfo, captionVisible, 1}},
- {2588, {wxAuiPaneInfo, centre, 0}},
- {2589, {wxAuiPaneInfo, centrePane, 0}},
- {2590, {wxAuiPaneInfo, closeButton, 1}},
- {2591, {wxAuiPaneInfo, defaultPane, 0}},
- {2592, {wxAuiPaneInfo, destroyOnClose, 1}},
- {2593, {wxAuiPaneInfo, direction, 1}},
- {2594, {wxAuiPaneInfo, dock, 0}},
- {2595, {wxAuiPaneInfo, dockable, 1}},
- {2596, {wxAuiPaneInfo, fixed, 0}},
- {2597, {wxAuiPaneInfo, float, 0}},
- {2598, {wxAuiPaneInfo, floatable, 1}},
- {2599, {wxAuiPaneInfo, floatingPosition_1, 1}},
- {2600, {wxAuiPaneInfo, floatingPosition_2, 2}},
- {2601, {wxAuiPaneInfo, floatingSize_1, 1}},
- {2602, {wxAuiPaneInfo, floatingSize_2, 2}},
- {2603, {wxAuiPaneInfo, gripper, 1}},
- {2604, {wxAuiPaneInfo, gripperTop, 1}},
- {2605, {wxAuiPaneInfo, hasBorder, 0}},
- {2606, {wxAuiPaneInfo, hasCaption, 0}},
- {2607, {wxAuiPaneInfo, hasCloseButton, 0}},
- {2608, {wxAuiPaneInfo, hasFlag, 1}},
- {2609, {wxAuiPaneInfo, hasGripper, 0}},
- {2610, {wxAuiPaneInfo, hasGripperTop, 0}},
- {2611, {wxAuiPaneInfo, hasMaximizeButton, 0}},
- {2612, {wxAuiPaneInfo, hasMinimizeButton, 0}},
- {2613, {wxAuiPaneInfo, hasPinButton, 0}},
- {2614, {wxAuiPaneInfo, hide, 0}},
- {2615, {wxAuiPaneInfo, isBottomDockable, 0}},
- {2616, {wxAuiPaneInfo, isDocked, 0}},
- {2617, {wxAuiPaneInfo, isFixed, 0}},
- {2618, {wxAuiPaneInfo, isFloatable, 0}},
- {2619, {wxAuiPaneInfo, isFloating, 0}},
- {2620, {wxAuiPaneInfo, isLeftDockable, 0}},
- {2621, {wxAuiPaneInfo, isMovable, 0}},
- {2622, {wxAuiPaneInfo, isOk, 0}},
- {2623, {wxAuiPaneInfo, isResizable, 0}},
- {2624, {wxAuiPaneInfo, isRightDockable, 0}},
- {2625, {wxAuiPaneInfo, isShown, 0}},
- {2626, {wxAuiPaneInfo, isToolbar, 0}},
- {2627, {wxAuiPaneInfo, isTopDockable, 0}},
- {2628, {wxAuiPaneInfo, layer, 1}},
- {2629, {wxAuiPaneInfo, left, 0}},
- {2630, {wxAuiPaneInfo, leftDockable, 1}},
- {2631, {wxAuiPaneInfo, maxSize_1, 1}},
- {2632, {wxAuiPaneInfo, maxSize_2, 2}},
- {2633, {wxAuiPaneInfo, maximizeButton, 1}},
- {2634, {wxAuiPaneInfo, minSize_1, 1}},
- {2635, {wxAuiPaneInfo, minSize_2, 2}},
- {2636, {wxAuiPaneInfo, minimizeButton, 1}},
- {2637, {wxAuiPaneInfo, movable, 1}},
- {2638, {wxAuiPaneInfo, name, 1}},
- {2639, {wxAuiPaneInfo, paneBorder, 1}},
- {2640, {wxAuiPaneInfo, pinButton, 1}},
- {2641, {wxAuiPaneInfo, position, 1}},
- {2642, {wxAuiPaneInfo, resizable, 1}},
- {2643, {wxAuiPaneInfo, right, 0}},
- {2644, {wxAuiPaneInfo, rightDockable, 1}},
- {2645, {wxAuiPaneInfo, row, 1}},
- {2646, {wxAuiPaneInfo, safeSet, 1}},
- {2647, {wxAuiPaneInfo, setFlag, 2}},
- {2648, {wxAuiPaneInfo, show, 1}},
- {2649, {wxAuiPaneInfo, toolbarPane, 0}},
- {2650, {wxAuiPaneInfo, top, 0}},
- {2651, {wxAuiPaneInfo, topDockable, 1}},
- {2652, {wxAuiPaneInfo, window, 1}},
- {2653, {wxAuiPaneInfo, getWindow, 0}},
- {2654, {wxAuiPaneInfo, getFrame, 0}},
- {2655, {wxAuiPaneInfo, getDirection, 0}},
- {2656, {wxAuiPaneInfo, getLayer, 0}},
- {2657, {wxAuiPaneInfo, getRow, 0}},
- {2658, {wxAuiPaneInfo, getPosition, 0}},
- {2659, {wxAuiPaneInfo, getFloatingPosition, 0}},
- {2660, {wxAuiPaneInfo, getFloatingSize, 0}},
- {2661, {wxAuiNotebook, new_0, 0}},
- {2662, {wxAuiNotebook, new_2, 2}},
- {2663, {wxAuiNotebook, addPage, 3}},
- {2664, {wxAuiNotebook, create, 2}},
- {2665, {wxAuiNotebook, deletePage, 1}},
- {2666, {wxAuiNotebook, getArtProvider, 0}},
- {2667, {wxAuiNotebook, getPage, 1}},
- {2668, {wxAuiNotebook, getPageBitmap, 1}},
- {2669, {wxAuiNotebook, getPageCount, 0}},
- {2670, {wxAuiNotebook, getPageIndex, 1}},
- {2671, {wxAuiNotebook, getPageText, 1}},
- {2672, {wxAuiNotebook, getSelection, 0}},
- {2673, {wxAuiNotebook, insertPage, 4}},
- {2674, {wxAuiNotebook, removePage, 1}},
- {2675, {wxAuiNotebook, setArtProvider, 1}},
- {2676, {wxAuiNotebook, setFont, 1}},
- {2677, {wxAuiNotebook, setPageBitmap, 2}},
- {2678, {wxAuiNotebook, setPageText, 2}},
- {2679, {wxAuiNotebook, setSelection, 1}},
- {2680, {wxAuiNotebook, setTabCtrlHeight, 1}},
- {2681, {wxAuiNotebook, setUniformBitmapSize, 1}},
- {2682, {wxAuiNotebook, 'Destroy', undefined}},
- {2683, {wxAuiTabArt, setFlags, 1}},
- {2684, {wxAuiTabArt, setMeasuringFont, 1}},
- {2685, {wxAuiTabArt, setNormalFont, 1}},
- {2686, {wxAuiTabArt, setSelectedFont, 1}},
- {2687, {wxAuiTabArt, setColour, 1}},
- {2688, {wxAuiTabArt, setActiveColour, 1}},
- {2689, {wxAuiDockArt, getColour, 1}},
- {2690, {wxAuiDockArt, getFont, 1}},
- {2691, {wxAuiDockArt, getMetric, 1}},
- {2692, {wxAuiDockArt, setColour, 2}},
- {2693, {wxAuiDockArt, setFont, 2}},
- {2694, {wxAuiDockArt, setMetric, 2}},
- {2695, {wxAuiSimpleTabArt, new, 0}},
- {2696, {wxAuiSimpleTabArt, 'Destroy', undefined}},
- {2697, {wxMDIParentFrame, new_0, 0}},
- {2698, {wxMDIParentFrame, new_4, 4}},
- {2699, {wxMDIParentFrame, destruct, 0}},
- {2700, {wxMDIParentFrame, activateNext, 0}},
- {2701, {wxMDIParentFrame, activatePrevious, 0}},
- {2702, {wxMDIParentFrame, arrangeIcons, 0}},
- {2703, {wxMDIParentFrame, cascade, 0}},
- {2704, {wxMDIParentFrame, create, 4}},
- {2705, {wxMDIParentFrame, getActiveChild, 0}},
- {2706, {wxMDIParentFrame, getClientWindow, 0}},
- {2707, {wxMDIParentFrame, tile, 1}},
- {2708, {wxMDIChildFrame, new_0, 0}},
- {2709, {wxMDIChildFrame, new_4, 4}},
- {2710, {wxMDIChildFrame, destruct, 0}},
- {2711, {wxMDIChildFrame, activate, 0}},
- {2712, {wxMDIChildFrame, create, 4}},
- {2713, {wxMDIChildFrame, maximize, 1}},
- {2714, {wxMDIChildFrame, restore, 0}},
- {2715, {wxMDIClientWindow, new_0, 0}},
- {2716, {wxMDIClientWindow, new_2, 2}},
- {2717, {wxMDIClientWindow, destruct, 0}},
- {2718, {wxMDIClientWindow, createClient, 2}},
- {2719, {wxLayoutAlgorithm, new, 0}},
- {2720, {wxLayoutAlgorithm, layoutFrame, 2}},
- {2721, {wxLayoutAlgorithm, layoutMDIFrame, 2}},
- {2722, {wxLayoutAlgorithm, layoutWindow, 2}},
- {2723, {wxLayoutAlgorithm, 'Destroy', undefined}},
- {2724, {wxEvent, getId, 0}},
- {2725, {wxEvent, getSkipped, 0}},
- {2726, {wxEvent, getTimestamp, 0}},
- {2727, {wxEvent, isCommandEvent, 0}},
- {2728, {wxEvent, resumePropagation, 1}},
- {2729, {wxEvent, shouldPropagate, 0}},
- {2730, {wxEvent, skip, 1}},
- {2731, {wxEvent, stopPropagation, 0}},
- {2732, {wxCommandEvent, getClientData, 0}},
- {2733, {wxCommandEvent, getExtraLong, 0}},
- {2734, {wxCommandEvent, getInt, 0}},
- {2735, {wxCommandEvent, getSelection, 0}},
- {2736, {wxCommandEvent, getString, 0}},
- {2737, {wxCommandEvent, isChecked, 0}},
- {2738, {wxCommandEvent, isSelection, 0}},
- {2739, {wxCommandEvent, setInt, 1}},
- {2740, {wxCommandEvent, setString, 1}},
- {2741, {wxScrollEvent, getOrientation, 0}},
- {2742, {wxScrollEvent, getPosition, 0}},
- {2743, {wxScrollWinEvent, getOrientation, 0}},
- {2744, {wxScrollWinEvent, getPosition, 0}},
- {2745, {wxMouseEvent, altDown, 0}},
- {2746, {wxMouseEvent, button, 1}},
- {2747, {wxMouseEvent, buttonDClick, 1}},
- {2748, {wxMouseEvent, buttonDown, 1}},
- {2749, {wxMouseEvent, buttonUp, 1}},
- {2750, {wxMouseEvent, cmdDown, 0}},
- {2751, {wxMouseEvent, controlDown, 0}},
- {2752, {wxMouseEvent, dragging, 0}},
- {2753, {wxMouseEvent, entering, 0}},
- {2754, {wxMouseEvent, getButton, 0}},
- {2757, {wxMouseEvent, getPosition, 0}},
- {2758, {wxMouseEvent, getLogicalPosition, 1}},
- {2759, {wxMouseEvent, getLinesPerAction, 0}},
- {2760, {wxMouseEvent, getWheelRotation, 0}},
- {2761, {wxMouseEvent, getWheelDelta, 0}},
- {2762, {wxMouseEvent, getX, 0}},
- {2763, {wxMouseEvent, getY, 0}},
- {2764, {wxMouseEvent, isButton, 0}},
- {2765, {wxMouseEvent, isPageScroll, 0}},
- {2766, {wxMouseEvent, leaving, 0}},
- {2767, {wxMouseEvent, leftDClick, 0}},
- {2768, {wxMouseEvent, leftDown, 0}},
- {2769, {wxMouseEvent, leftIsDown, 0}},
- {2770, {wxMouseEvent, leftUp, 0}},
- {2771, {wxMouseEvent, metaDown, 0}},
- {2772, {wxMouseEvent, middleDClick, 0}},
- {2773, {wxMouseEvent, middleDown, 0}},
- {2774, {wxMouseEvent, middleIsDown, 0}},
- {2775, {wxMouseEvent, middleUp, 0}},
- {2776, {wxMouseEvent, moving, 0}},
- {2777, {wxMouseEvent, rightDClick, 0}},
- {2778, {wxMouseEvent, rightDown, 0}},
- {2779, {wxMouseEvent, rightIsDown, 0}},
- {2780, {wxMouseEvent, rightUp, 0}},
- {2781, {wxMouseEvent, shiftDown, 0}},
- {2782, {wxSetCursorEvent, getCursor, 0}},
- {2783, {wxSetCursorEvent, getX, 0}},
- {2784, {wxSetCursorEvent, getY, 0}},
- {2785, {wxSetCursorEvent, hasCursor, 0}},
- {2786, {wxSetCursorEvent, setCursor, 1}},
- {2787, {wxKeyEvent, altDown, 0}},
- {2788, {wxKeyEvent, cmdDown, 0}},
- {2789, {wxKeyEvent, controlDown, 0}},
- {2790, {wxKeyEvent, getKeyCode, 0}},
- {2791, {wxKeyEvent, getModifiers, 0}},
- {2794, {wxKeyEvent, getPosition, 0}},
- {2795, {wxKeyEvent, getRawKeyCode, 0}},
- {2796, {wxKeyEvent, getRawKeyFlags, 0}},
- {2797, {wxKeyEvent, getUnicodeKey, 0}},
- {2798, {wxKeyEvent, getX, 0}},
- {2799, {wxKeyEvent, getY, 0}},
- {2800, {wxKeyEvent, hasModifiers, 0}},
- {2801, {wxKeyEvent, metaDown, 0}},
- {2802, {wxKeyEvent, shiftDown, 0}},
- {2803, {wxSizeEvent, getSize, 0}},
- {2804, {wxMoveEvent, getPosition, 0}},
- {2805, {wxEraseEvent, getDC, 0}},
- {2806, {wxFocusEvent, getWindow, 0}},
- {2807, {wxChildFocusEvent, getWindow, 0}},
- {2808, {wxMenuEvent, getMenu, 0}},
- {2809, {wxMenuEvent, getMenuId, 0}},
- {2810, {wxMenuEvent, isPopup, 0}},
- {2811, {wxCloseEvent, canVeto, 0}},
- {2812, {wxCloseEvent, getLoggingOff, 0}},
- {2813, {wxCloseEvent, setCanVeto, 1}},
- {2814, {wxCloseEvent, setLoggingOff, 1}},
- {2815, {wxCloseEvent, veto, 1}},
- {2816, {wxShowEvent, setShow, 1}},
- {2817, {wxShowEvent, getShow, 0}},
- {2818, {wxIconizeEvent, iconized, 0}},
- {2819, {wxJoystickEvent, buttonDown, 1}},
- {2820, {wxJoystickEvent, buttonIsDown, 1}},
- {2821, {wxJoystickEvent, buttonUp, 1}},
- {2822, {wxJoystickEvent, getButtonChange, 0}},
- {2823, {wxJoystickEvent, getButtonState, 0}},
- {2824, {wxJoystickEvent, getJoystick, 0}},
- {2825, {wxJoystickEvent, getPosition, 0}},
- {2826, {wxJoystickEvent, getZPosition, 0}},
- {2827, {wxJoystickEvent, isButton, 0}},
- {2828, {wxJoystickEvent, isMove, 0}},
- {2829, {wxJoystickEvent, isZMove, 0}},
- {2830, {wxUpdateUIEvent, canUpdate, 1}},
- {2831, {wxUpdateUIEvent, check, 1}},
- {2832, {wxUpdateUIEvent, enable, 1}},
- {2833, {wxUpdateUIEvent, show, 1}},
- {2834, {wxUpdateUIEvent, getChecked, 0}},
- {2835, {wxUpdateUIEvent, getEnabled, 0}},
- {2836, {wxUpdateUIEvent, getShown, 0}},
- {2837, {wxUpdateUIEvent, getSetChecked, 0}},
- {2838, {wxUpdateUIEvent, getSetEnabled, 0}},
- {2839, {wxUpdateUIEvent, getSetShown, 0}},
- {2840, {wxUpdateUIEvent, getSetText, 0}},
- {2841, {wxUpdateUIEvent, getText, 0}},
- {2842, {wxUpdateUIEvent, getMode, 0}},
- {2843, {wxUpdateUIEvent, getUpdateInterval, 0}},
- {2844, {wxUpdateUIEvent, resetUpdateTime, 0}},
- {2845, {wxUpdateUIEvent, setMode, 1}},
- {2846, {wxUpdateUIEvent, setText, 1}},
- {2847, {wxUpdateUIEvent, setUpdateInterval, 1}},
- {2848, {wxMouseCaptureChangedEvent, getCapturedWindow, 0}},
- {2849, {wxPaletteChangedEvent, setChangedWindow, 1}},
- {2850, {wxPaletteChangedEvent, getChangedWindow, 0}},
- {2851, {wxQueryNewPaletteEvent, setPaletteRealized, 1}},
- {2852, {wxQueryNewPaletteEvent, getPaletteRealized, 0}},
- {2853, {wxNavigationKeyEvent, getDirection, 0}},
- {2854, {wxNavigationKeyEvent, setDirection, 1}},
- {2855, {wxNavigationKeyEvent, isWindowChange, 0}},
- {2856, {wxNavigationKeyEvent, setWindowChange, 1}},
- {2857, {wxNavigationKeyEvent, isFromTab, 0}},
- {2858, {wxNavigationKeyEvent, setFromTab, 1}},
- {2859, {wxNavigationKeyEvent, getCurrentFocus, 0}},
- {2860, {wxNavigationKeyEvent, setCurrentFocus, 1}},
- {2861, {wxHelpEvent, getOrigin, 0}},
- {2862, {wxHelpEvent, getPosition, 0}},
- {2863, {wxHelpEvent, setOrigin, 1}},
- {2864, {wxHelpEvent, setPosition, 1}},
- {2865, {wxContextMenuEvent, getPosition, 0}},
- {2866, {wxContextMenuEvent, setPosition, 1}},
- {2867, {wxIdleEvent, canSend, 1}},
- {2868, {wxIdleEvent, getMode, 0}},
- {2869, {wxIdleEvent, requestMore, 1}},
- {2870, {wxIdleEvent, moreRequested, 0}},
- {2871, {wxIdleEvent, setMode, 1}},
- {2872, {wxGridEvent, altDown, 0}},
- {2873, {wxGridEvent, controlDown, 0}},
- {2874, {wxGridEvent, getCol, 0}},
- {2875, {wxGridEvent, getPosition, 0}},
- {2876, {wxGridEvent, getRow, 0}},
- {2877, {wxGridEvent, metaDown, 0}},
- {2878, {wxGridEvent, selecting, 0}},
- {2879, {wxGridEvent, shiftDown, 0}},
- {2880, {wxNotifyEvent, allow, 0}},
- {2881, {wxNotifyEvent, isAllowed, 0}},
- {2882, {wxNotifyEvent, veto, 0}},
- {2883, {wxSashEvent, getEdge, 0}},
- {2884, {wxSashEvent, getDragRect, 0}},
- {2885, {wxSashEvent, getDragStatus, 0}},
- {2886, {wxListEvent, getCacheFrom, 0}},
- {2887, {wxListEvent, getCacheTo, 0}},
- {2888, {wxListEvent, getKeyCode, 0}},
- {2889, {wxListEvent, getIndex, 0}},
- {2890, {wxListEvent, getColumn, 0}},
- {2891, {wxListEvent, getPoint, 0}},
- {2892, {wxListEvent, getLabel, 0}},
- {2893, {wxListEvent, getText, 0}},
- {2894, {wxListEvent, getImage, 0}},
- {2895, {wxListEvent, getData, 0}},
- {2896, {wxListEvent, getMask, 0}},
- {2897, {wxListEvent, getItem, 0}},
- {2898, {wxListEvent, isEditCancelled, 0}},
- {2899, {wxDateEvent, getDate, 0}},
- {2900, {wxCalendarEvent, getWeekDay, 0}},
- {2901, {wxFileDirPickerEvent, getPath, 0}},
- {2902, {wxColourPickerEvent, getColour, 0}},
- {2903, {wxFontPickerEvent, getFont, 0}},
- {2904, {wxStyledTextEvent, getPosition, 0}},
- {2905, {wxStyledTextEvent, getKey, 0}},
- {2906, {wxStyledTextEvent, getModifiers, 0}},
- {2907, {wxStyledTextEvent, getModificationType, 0}},
- {2908, {wxStyledTextEvent, getText, 0}},
- {2909, {wxStyledTextEvent, getLength, 0}},
- {2910, {wxStyledTextEvent, getLinesAdded, 0}},
- {2911, {wxStyledTextEvent, getLine, 0}},
- {2912, {wxStyledTextEvent, getFoldLevelNow, 0}},
- {2913, {wxStyledTextEvent, getFoldLevelPrev, 0}},
- {2914, {wxStyledTextEvent, getMargin, 0}},
- {2915, {wxStyledTextEvent, getMessage, 0}},
- {2916, {wxStyledTextEvent, getWParam, 0}},
- {2917, {wxStyledTextEvent, getLParam, 0}},
- {2918, {wxStyledTextEvent, getListType, 0}},
- {2919, {wxStyledTextEvent, getX, 0}},
- {2920, {wxStyledTextEvent, getY, 0}},
- {2921, {wxStyledTextEvent, getDragText, 0}},
- {2922, {wxStyledTextEvent, getDragAllowMove, 0}},
- {2923, {wxStyledTextEvent, getDragResult, 0}},
- {2924, {wxStyledTextEvent, getShift, 0}},
- {2925, {wxStyledTextEvent, getControl, 0}},
- {2926, {wxStyledTextEvent, getAlt, 0}},
- {2927, {utils, getKeyState, 1}},
- {2928, {utils, getMousePosition, 2}},
- {2929, {utils, getMouseState, 0}},
- {2930, {utils, setDetectableAutoRepeat, 1}},
- {2931, {utils, bell, 0}},
- {2932, {utils, findMenuItemId, 3}},
- {2933, {utils, genericFindWindowAtPoint, 1}},
- {2934, {utils, findWindowAtPoint, 1}},
- {2935, {utils, beginBusyCursor, 1}},
- {2936, {utils, endBusyCursor, 0}},
- {2937, {utils, isBusy, 0}},
- {2938, {utils, shutdown, 1}},
- {2939, {utils, shell, 1}},
- {2940, {utils, launchDefaultBrowser, 2}},
- {2941, {utils, getEmailAddress, 0}},
- {2942, {utils, getUserId, 0}},
- {2943, {utils, getHomeDir, 0}},
- {2944, {utils, newId, 0}},
- {2945, {utils, registerId, 1}},
- {2946, {utils, getCurrentId, 0}},
- {2947, {utils, getOsDescription, 0}},
- {2948, {utils, isPlatformLittleEndian, 0}},
- {2949, {utils, isPlatform64Bit, 0}},
- {2950, {gdicmn, displaySize, 2}},
- {2951, {gdicmn, setCursor, 1}},
- {2952, {wxPrintout, new, 1}},
- {2953, {wxPrintout, destruct, 0}},
- {2954, {wxPrintout, getDC, 0}},
- {2955, {wxPrintout, getPageSizeMM, 2}},
- {2956, {wxPrintout, getPageSizePixels, 2}},
- {2957, {wxPrintout, getPaperRectPixels, 0}},
- {2958, {wxPrintout, getPPIPrinter, 2}},
- {2959, {wxPrintout, getPPIScreen, 2}},
- {2960, {wxPrintout, getTitle, 0}},
- {2961, {wxPrintout, isPreview, 0}},
- {2962, {wxPrintout, fitThisSizeToPaper, 1}},
- {2963, {wxPrintout, fitThisSizeToPage, 1}},
- {2964, {wxPrintout, fitThisSizeToPageMargins, 2}},
- {2965, {wxPrintout, mapScreenSizeToPaper, 0}},
- {2966, {wxPrintout, mapScreenSizeToPage, 0}},
- {2967, {wxPrintout, mapScreenSizeToPageMargins, 1}},
- {2968, {wxPrintout, mapScreenSizeToDevice, 0}},
- {2969, {wxPrintout, getLogicalPaperRect, 0}},
- {2970, {wxPrintout, getLogicalPageRect, 0}},
- {2971, {wxPrintout, getLogicalPageMarginsRect, 1}},
- {2972, {wxPrintout, setLogicalOrigin, 2}},
- {2973, {wxPrintout, offsetLogicalOrigin, 2}},
- {2974, {wxStyledTextCtrl, new_2, 2}},
- {2975, {wxStyledTextCtrl, new_0, 0}},
- {2976, {wxStyledTextCtrl, destruct, 0}},
- {2977, {wxStyledTextCtrl, create, 2}},
- {2978, {wxStyledTextCtrl, addText, 1}},
- {2979, {wxStyledTextCtrl, addStyledText, 1}},
- {2980, {wxStyledTextCtrl, insertText, 2}},
- {2981, {wxStyledTextCtrl, clearAll, 0}},
- {2982, {wxStyledTextCtrl, clearDocumentStyle, 0}},
- {2983, {wxStyledTextCtrl, getLength, 0}},
- {2984, {wxStyledTextCtrl, getCharAt, 1}},
- {2985, {wxStyledTextCtrl, getCurrentPos, 0}},
- {2986, {wxStyledTextCtrl, getAnchor, 0}},
- {2987, {wxStyledTextCtrl, getStyleAt, 1}},
- {2988, {wxStyledTextCtrl, redo, 0}},
- {2989, {wxStyledTextCtrl, setUndoCollection, 1}},
- {2990, {wxStyledTextCtrl, selectAll, 0}},
- {2991, {wxStyledTextCtrl, setSavePoint, 0}},
- {2992, {wxStyledTextCtrl, getStyledText, 2}},
- {2993, {wxStyledTextCtrl, canRedo, 0}},
- {2994, {wxStyledTextCtrl, markerLineFromHandle, 1}},
- {2995, {wxStyledTextCtrl, markerDeleteHandle, 1}},
- {2996, {wxStyledTextCtrl, getUndoCollection, 0}},
- {2997, {wxStyledTextCtrl, getViewWhiteSpace, 0}},
- {2998, {wxStyledTextCtrl, setViewWhiteSpace, 1}},
- {2999, {wxStyledTextCtrl, positionFromPoint, 1}},
- {3000, {wxStyledTextCtrl, positionFromPointClose, 2}},
- {3001, {wxStyledTextCtrl, gotoLine, 1}},
- {3002, {wxStyledTextCtrl, gotoPos, 1}},
- {3003, {wxStyledTextCtrl, setAnchor, 1}},
- {3004, {wxStyledTextCtrl, getCurLine, 1}},
- {3005, {wxStyledTextCtrl, getEndStyled, 0}},
- {3006, {wxStyledTextCtrl, convertEOLs, 1}},
- {3007, {wxStyledTextCtrl, getEOLMode, 0}},
- {3008, {wxStyledTextCtrl, setEOLMode, 1}},
- {3009, {wxStyledTextCtrl, startStyling, 2}},
- {3010, {wxStyledTextCtrl, setStyling, 2}},
- {3011, {wxStyledTextCtrl, getBufferedDraw, 0}},
- {3012, {wxStyledTextCtrl, setBufferedDraw, 1}},
- {3013, {wxStyledTextCtrl, setTabWidth, 1}},
- {3014, {wxStyledTextCtrl, getTabWidth, 0}},
- {3015, {wxStyledTextCtrl, setCodePage, 1}},
- {3016, {wxStyledTextCtrl, markerDefine, 3}},
- {3017, {wxStyledTextCtrl, markerSetForeground, 2}},
- {3018, {wxStyledTextCtrl, markerSetBackground, 2}},
- {3019, {wxStyledTextCtrl, markerAdd, 2}},
- {3020, {wxStyledTextCtrl, markerDelete, 2}},
- {3021, {wxStyledTextCtrl, markerDeleteAll, 1}},
- {3022, {wxStyledTextCtrl, markerGet, 1}},
- {3023, {wxStyledTextCtrl, markerNext, 2}},
- {3024, {wxStyledTextCtrl, markerPrevious, 2}},
- {3025, {wxStyledTextCtrl, markerDefineBitmap, 2}},
- {3026, {wxStyledTextCtrl, markerAddSet, 2}},
- {3027, {wxStyledTextCtrl, markerSetAlpha, 2}},
- {3028, {wxStyledTextCtrl, setMarginType, 2}},
- {3029, {wxStyledTextCtrl, getMarginType, 1}},
- {3030, {wxStyledTextCtrl, setMarginWidth, 2}},
- {3031, {wxStyledTextCtrl, getMarginWidth, 1}},
- {3032, {wxStyledTextCtrl, setMarginMask, 2}},
- {3033, {wxStyledTextCtrl, getMarginMask, 1}},
- {3034, {wxStyledTextCtrl, setMarginSensitive, 2}},
- {3035, {wxStyledTextCtrl, getMarginSensitive, 1}},
- {3036, {wxStyledTextCtrl, styleClearAll, 0}},
- {3037, {wxStyledTextCtrl, styleSetForeground, 2}},
- {3038, {wxStyledTextCtrl, styleSetBackground, 2}},
- {3039, {wxStyledTextCtrl, styleSetBold, 2}},
- {3040, {wxStyledTextCtrl, styleSetItalic, 2}},
- {3041, {wxStyledTextCtrl, styleSetSize, 2}},
- {3042, {wxStyledTextCtrl, styleSetFaceName, 2}},
- {3043, {wxStyledTextCtrl, styleSetEOLFilled, 2}},
- {3044, {wxStyledTextCtrl, styleResetDefault, 0}},
- {3045, {wxStyledTextCtrl, styleSetUnderline, 2}},
- {3046, {wxStyledTextCtrl, styleSetCase, 2}},
- {3047, {wxStyledTextCtrl, styleSetHotSpot, 2}},
- {3048, {wxStyledTextCtrl, setSelForeground, 2}},
- {3049, {wxStyledTextCtrl, setSelBackground, 2}},
- {3050, {wxStyledTextCtrl, getSelAlpha, 0}},
- {3051, {wxStyledTextCtrl, setSelAlpha, 1}},
- {3052, {wxStyledTextCtrl, setCaretForeground, 1}},
- {3053, {wxStyledTextCtrl, cmdKeyAssign, 3}},
- {3054, {wxStyledTextCtrl, cmdKeyClear, 2}},
- {3055, {wxStyledTextCtrl, cmdKeyClearAll, 0}},
- {3056, {wxStyledTextCtrl, setStyleBytes, 2}},
- {3057, {wxStyledTextCtrl, styleSetVisible, 2}},
- {3058, {wxStyledTextCtrl, getCaretPeriod, 0}},
- {3059, {wxStyledTextCtrl, setCaretPeriod, 1}},
- {3060, {wxStyledTextCtrl, setWordChars, 1}},
- {3061, {wxStyledTextCtrl, beginUndoAction, 0}},
- {3062, {wxStyledTextCtrl, endUndoAction, 0}},
- {3063, {wxStyledTextCtrl, indicatorSetStyle, 2}},
- {3064, {wxStyledTextCtrl, indicatorGetStyle, 1}},
- {3065, {wxStyledTextCtrl, indicatorSetForeground, 2}},
- {3066, {wxStyledTextCtrl, indicatorGetForeground, 1}},
- {3067, {wxStyledTextCtrl, setWhitespaceForeground, 2}},
- {3068, {wxStyledTextCtrl, setWhitespaceBackground, 2}},
- {3069, {wxStyledTextCtrl, getStyleBits, 0}},
- {3070, {wxStyledTextCtrl, setLineState, 2}},
- {3071, {wxStyledTextCtrl, getLineState, 1}},
- {3072, {wxStyledTextCtrl, getMaxLineState, 0}},
- {3073, {wxStyledTextCtrl, getCaretLineVisible, 0}},
- {3074, {wxStyledTextCtrl, setCaretLineVisible, 1}},
- {3075, {wxStyledTextCtrl, getCaretLineBackground, 0}},
- {3076, {wxStyledTextCtrl, setCaretLineBackground, 1}},
- {3077, {wxStyledTextCtrl, autoCompShow, 2}},
- {3078, {wxStyledTextCtrl, autoCompCancel, 0}},
- {3079, {wxStyledTextCtrl, autoCompActive, 0}},
- {3080, {wxStyledTextCtrl, autoCompPosStart, 0}},
- {3081, {wxStyledTextCtrl, autoCompComplete, 0}},
- {3082, {wxStyledTextCtrl, autoCompStops, 1}},
- {3083, {wxStyledTextCtrl, autoCompSetSeparator, 1}},
- {3084, {wxStyledTextCtrl, autoCompGetSeparator, 0}},
- {3085, {wxStyledTextCtrl, autoCompSelect, 1}},
- {3086, {wxStyledTextCtrl, autoCompSetCancelAtStart, 1}},
- {3087, {wxStyledTextCtrl, autoCompGetCancelAtStart, 0}},
- {3088, {wxStyledTextCtrl, autoCompSetFillUps, 1}},
- {3089, {wxStyledTextCtrl, autoCompSetChooseSingle, 1}},
- {3090, {wxStyledTextCtrl, autoCompGetChooseSingle, 0}},
- {3091, {wxStyledTextCtrl, autoCompSetIgnoreCase, 1}},
- {3092, {wxStyledTextCtrl, autoCompGetIgnoreCase, 0}},
- {3093, {wxStyledTextCtrl, userListShow, 2}},
- {3094, {wxStyledTextCtrl, autoCompSetAutoHide, 1}},
- {3095, {wxStyledTextCtrl, autoCompGetAutoHide, 0}},
- {3096, {wxStyledTextCtrl, autoCompSetDropRestOfWord, 1}},
- {3097, {wxStyledTextCtrl, autoCompGetDropRestOfWord, 0}},
- {3098, {wxStyledTextCtrl, registerImage, 2}},
- {3099, {wxStyledTextCtrl, clearRegisteredImages, 0}},
- {3100, {wxStyledTextCtrl, autoCompGetTypeSeparator, 0}},
- {3101, {wxStyledTextCtrl, autoCompSetTypeSeparator, 1}},
- {3102, {wxStyledTextCtrl, autoCompSetMaxWidth, 1}},
- {3103, {wxStyledTextCtrl, autoCompGetMaxWidth, 0}},
- {3104, {wxStyledTextCtrl, autoCompSetMaxHeight, 1}},
- {3105, {wxStyledTextCtrl, autoCompGetMaxHeight, 0}},
- {3106, {wxStyledTextCtrl, setIndent, 1}},
- {3107, {wxStyledTextCtrl, getIndent, 0}},
- {3108, {wxStyledTextCtrl, setUseTabs, 1}},
- {3109, {wxStyledTextCtrl, getUseTabs, 0}},
- {3110, {wxStyledTextCtrl, setLineIndentation, 2}},
- {3111, {wxStyledTextCtrl, getLineIndentation, 1}},
- {3112, {wxStyledTextCtrl, getLineIndentPosition, 1}},
- {3113, {wxStyledTextCtrl, getColumn, 1}},
- {3114, {wxStyledTextCtrl, setUseHorizontalScrollBar, 1}},
- {3115, {wxStyledTextCtrl, getUseHorizontalScrollBar, 0}},
- {3116, {wxStyledTextCtrl, setIndentationGuides, 1}},
- {3117, {wxStyledTextCtrl, getIndentationGuides, 0}},
- {3118, {wxStyledTextCtrl, setHighlightGuide, 1}},
- {3119, {wxStyledTextCtrl, getHighlightGuide, 0}},
- {3120, {wxStyledTextCtrl, getLineEndPosition, 1}},
- {3121, {wxStyledTextCtrl, getCodePage, 0}},
- {3122, {wxStyledTextCtrl, getCaretForeground, 0}},
- {3123, {wxStyledTextCtrl, getReadOnly, 0}},
- {3124, {wxStyledTextCtrl, setCurrentPos, 1}},
- {3125, {wxStyledTextCtrl, setSelectionStart, 1}},
- {3126, {wxStyledTextCtrl, getSelectionStart, 0}},
- {3127, {wxStyledTextCtrl, setSelectionEnd, 1}},
- {3128, {wxStyledTextCtrl, getSelectionEnd, 0}},
- {3129, {wxStyledTextCtrl, setPrintMagnification, 1}},
- {3130, {wxStyledTextCtrl, getPrintMagnification, 0}},
- {3131, {wxStyledTextCtrl, setPrintColourMode, 1}},
- {3132, {wxStyledTextCtrl, getPrintColourMode, 0}},
- {3133, {wxStyledTextCtrl, findText, 4}},
- {3134, {wxStyledTextCtrl, formatRange, 7}},
- {3135, {wxStyledTextCtrl, getFirstVisibleLine, 0}},
- {3136, {wxStyledTextCtrl, getLine, 1}},
- {3137, {wxStyledTextCtrl, getLineCount, 0}},
- {3138, {wxStyledTextCtrl, setMarginLeft, 1}},
- {3139, {wxStyledTextCtrl, getMarginLeft, 0}},
- {3140, {wxStyledTextCtrl, setMarginRight, 1}},
- {3141, {wxStyledTextCtrl, getMarginRight, 0}},
- {3142, {wxStyledTextCtrl, getModify, 0}},
- {3143, {wxStyledTextCtrl, setSelection, 2}},
- {3144, {wxStyledTextCtrl, getSelectedText, 0}},
- {3145, {wxStyledTextCtrl, getTextRange, 2}},
- {3146, {wxStyledTextCtrl, hideSelection, 1}},
- {3147, {wxStyledTextCtrl, lineFromPosition, 1}},
- {3148, {wxStyledTextCtrl, positionFromLine, 1}},
- {3149, {wxStyledTextCtrl, lineScroll, 2}},
- {3150, {wxStyledTextCtrl, ensureCaretVisible, 0}},
- {3151, {wxStyledTextCtrl, replaceSelection, 1}},
- {3152, {wxStyledTextCtrl, setReadOnly, 1}},
- {3153, {wxStyledTextCtrl, canPaste, 0}},
- {3154, {wxStyledTextCtrl, canUndo, 0}},
- {3155, {wxStyledTextCtrl, emptyUndoBuffer, 0}},
- {3156, {wxStyledTextCtrl, undo, 0}},
- {3157, {wxStyledTextCtrl, cut, 0}},
- {3158, {wxStyledTextCtrl, copy, 0}},
- {3159, {wxStyledTextCtrl, paste, 0}},
- {3160, {wxStyledTextCtrl, clear, 0}},
- {3161, {wxStyledTextCtrl, setText, 1}},
- {3162, {wxStyledTextCtrl, getText, 0}},
- {3163, {wxStyledTextCtrl, getTextLength, 0}},
- {3164, {wxStyledTextCtrl, getOvertype, 0}},
- {3165, {wxStyledTextCtrl, setCaretWidth, 1}},
- {3166, {wxStyledTextCtrl, getCaretWidth, 0}},
- {3167, {wxStyledTextCtrl, setTargetStart, 1}},
- {3168, {wxStyledTextCtrl, getTargetStart, 0}},
- {3169, {wxStyledTextCtrl, setTargetEnd, 1}},
- {3170, {wxStyledTextCtrl, getTargetEnd, 0}},
- {3171, {wxStyledTextCtrl, replaceTarget, 1}},
- {3172, {wxStyledTextCtrl, searchInTarget, 1}},
- {3173, {wxStyledTextCtrl, setSearchFlags, 1}},
- {3174, {wxStyledTextCtrl, getSearchFlags, 0}},
- {3175, {wxStyledTextCtrl, callTipShow, 2}},
- {3176, {wxStyledTextCtrl, callTipCancel, 0}},
- {3177, {wxStyledTextCtrl, callTipActive, 0}},
- {3178, {wxStyledTextCtrl, callTipPosAtStart, 0}},
- {3179, {wxStyledTextCtrl, callTipSetHighlight, 2}},
- {3180, {wxStyledTextCtrl, callTipSetBackground, 1}},
- {3181, {wxStyledTextCtrl, callTipSetForeground, 1}},
- {3182, {wxStyledTextCtrl, callTipSetForegroundHighlight, 1}},
- {3183, {wxStyledTextCtrl, callTipUseStyle, 1}},
- {3184, {wxStyledTextCtrl, visibleFromDocLine, 1}},
- {3185, {wxStyledTextCtrl, docLineFromVisible, 1}},
- {3186, {wxStyledTextCtrl, wrapCount, 1}},
- {3187, {wxStyledTextCtrl, setFoldLevel, 2}},
- {3188, {wxStyledTextCtrl, getFoldLevel, 1}},
- {3189, {wxStyledTextCtrl, getLastChild, 2}},
- {3190, {wxStyledTextCtrl, getFoldParent, 1}},
- {3191, {wxStyledTextCtrl, showLines, 2}},
- {3192, {wxStyledTextCtrl, hideLines, 2}},
- {3193, {wxStyledTextCtrl, getLineVisible, 1}},
- {3194, {wxStyledTextCtrl, setFoldExpanded, 2}},
- {3195, {wxStyledTextCtrl, getFoldExpanded, 1}},
- {3196, {wxStyledTextCtrl, toggleFold, 1}},
- {3197, {wxStyledTextCtrl, ensureVisible, 1}},
- {3198, {wxStyledTextCtrl, setFoldFlags, 1}},
- {3199, {wxStyledTextCtrl, ensureVisibleEnforcePolicy, 1}},
- {3200, {wxStyledTextCtrl, setTabIndents, 1}},
- {3201, {wxStyledTextCtrl, getTabIndents, 0}},
- {3202, {wxStyledTextCtrl, setBackSpaceUnIndents, 1}},
- {3203, {wxStyledTextCtrl, getBackSpaceUnIndents, 0}},
- {3204, {wxStyledTextCtrl, setMouseDwellTime, 1}},
- {3205, {wxStyledTextCtrl, getMouseDwellTime, 0}},
- {3206, {wxStyledTextCtrl, wordStartPosition, 2}},
- {3207, {wxStyledTextCtrl, wordEndPosition, 2}},
- {3208, {wxStyledTextCtrl, setWrapMode, 1}},
- {3209, {wxStyledTextCtrl, getWrapMode, 0}},
- {3210, {wxStyledTextCtrl, setWrapVisualFlags, 1}},
- {3211, {wxStyledTextCtrl, getWrapVisualFlags, 0}},
- {3212, {wxStyledTextCtrl, setWrapVisualFlagsLocation, 1}},
- {3213, {wxStyledTextCtrl, getWrapVisualFlagsLocation, 0}},
- {3214, {wxStyledTextCtrl, setWrapStartIndent, 1}},
- {3215, {wxStyledTextCtrl, getWrapStartIndent, 0}},
- {3216, {wxStyledTextCtrl, setLayoutCache, 1}},
- {3217, {wxStyledTextCtrl, getLayoutCache, 0}},
- {3218, {wxStyledTextCtrl, setScrollWidth, 1}},
- {3219, {wxStyledTextCtrl, getScrollWidth, 0}},
- {3220, {wxStyledTextCtrl, textWidth, 2}},
- {3221, {wxStyledTextCtrl, getEndAtLastLine, 0}},
- {3222, {wxStyledTextCtrl, textHeight, 1}},
- {3223, {wxStyledTextCtrl, setUseVerticalScrollBar, 1}},
- {3224, {wxStyledTextCtrl, getUseVerticalScrollBar, 0}},
- {3225, {wxStyledTextCtrl, appendText, 1}},
- {3226, {wxStyledTextCtrl, getTwoPhaseDraw, 0}},
- {3227, {wxStyledTextCtrl, setTwoPhaseDraw, 1}},
- {3228, {wxStyledTextCtrl, targetFromSelection, 0}},
- {3229, {wxStyledTextCtrl, linesJoin, 0}},
- {3230, {wxStyledTextCtrl, linesSplit, 1}},
- {3231, {wxStyledTextCtrl, setFoldMarginColour, 2}},
- {3232, {wxStyledTextCtrl, setFoldMarginHiColour, 2}},
- {3233, {wxStyledTextCtrl, lineDown, 0}},
- {3234, {wxStyledTextCtrl, lineDownExtend, 0}},
- {3235, {wxStyledTextCtrl, lineUp, 0}},
- {3236, {wxStyledTextCtrl, lineUpExtend, 0}},
- {3237, {wxStyledTextCtrl, charLeft, 0}},
- {3238, {wxStyledTextCtrl, charLeftExtend, 0}},
- {3239, {wxStyledTextCtrl, charRight, 0}},
- {3240, {wxStyledTextCtrl, charRightExtend, 0}},
- {3241, {wxStyledTextCtrl, wordLeft, 0}},
- {3242, {wxStyledTextCtrl, wordLeftExtend, 0}},
- {3243, {wxStyledTextCtrl, wordRight, 0}},
- {3244, {wxStyledTextCtrl, wordRightExtend, 0}},
- {3245, {wxStyledTextCtrl, home, 0}},
- {3246, {wxStyledTextCtrl, homeExtend, 0}},
- {3247, {wxStyledTextCtrl, lineEnd, 0}},
- {3248, {wxStyledTextCtrl, lineEndExtend, 0}},
- {3249, {wxStyledTextCtrl, documentStart, 0}},
- {3250, {wxStyledTextCtrl, documentStartExtend, 0}},
- {3251, {wxStyledTextCtrl, documentEnd, 0}},
- {3252, {wxStyledTextCtrl, documentEndExtend, 0}},
- {3253, {wxStyledTextCtrl, pageUp, 0}},
- {3254, {wxStyledTextCtrl, pageUpExtend, 0}},
- {3255, {wxStyledTextCtrl, pageDown, 0}},
- {3256, {wxStyledTextCtrl, pageDownExtend, 0}},
- {3257, {wxStyledTextCtrl, editToggleOvertype, 0}},
- {3258, {wxStyledTextCtrl, cancel, 0}},
- {3259, {wxStyledTextCtrl, deleteBack, 0}},
- {3260, {wxStyledTextCtrl, tab, 0}},
- {3261, {wxStyledTextCtrl, backTab, 0}},
- {3262, {wxStyledTextCtrl, newLine, 0}},
- {3263, {wxStyledTextCtrl, formFeed, 0}},
- {3264, {wxStyledTextCtrl, vCHome, 0}},
- {3265, {wxStyledTextCtrl, vCHomeExtend, 0}},
- {3266, {wxStyledTextCtrl, zoomIn, 0}},
- {3267, {wxStyledTextCtrl, zoomOut, 0}},
- {3268, {wxStyledTextCtrl, delWordLeft, 0}},
- {3269, {wxStyledTextCtrl, delWordRight, 0}},
- {3270, {wxStyledTextCtrl, lineCut, 0}},
- {3271, {wxStyledTextCtrl, lineDelete, 0}},
- {3272, {wxStyledTextCtrl, lineTranspose, 0}},
- {3273, {wxStyledTextCtrl, lineDuplicate, 0}},
- {3274, {wxStyledTextCtrl, lowerCase, 0}},
- {3275, {wxStyledTextCtrl, upperCase, 0}},
- {3276, {wxStyledTextCtrl, lineScrollDown, 0}},
- {3277, {wxStyledTextCtrl, lineScrollUp, 0}},
- {3278, {wxStyledTextCtrl, deleteBackNotLine, 0}},
- {3279, {wxStyledTextCtrl, homeDisplay, 0}},
- {3280, {wxStyledTextCtrl, homeDisplayExtend, 0}},
- {3281, {wxStyledTextCtrl, lineEndDisplay, 0}},
- {3282, {wxStyledTextCtrl, lineEndDisplayExtend, 0}},
- {3283, {wxStyledTextCtrl, homeWrapExtend, 0}},
- {3284, {wxStyledTextCtrl, lineEndWrap, 0}},
- {3285, {wxStyledTextCtrl, lineEndWrapExtend, 0}},
- {3286, {wxStyledTextCtrl, vCHomeWrap, 0}},
- {3287, {wxStyledTextCtrl, vCHomeWrapExtend, 0}},
- {3288, {wxStyledTextCtrl, lineCopy, 0}},
- {3289, {wxStyledTextCtrl, moveCaretInsideView, 0}},
- {3290, {wxStyledTextCtrl, lineLength, 1}},
- {3291, {wxStyledTextCtrl, braceHighlight, 2}},
- {3292, {wxStyledTextCtrl, braceBadLight, 1}},
- {3293, {wxStyledTextCtrl, braceMatch, 1}},
- {3294, {wxStyledTextCtrl, getViewEOL, 0}},
- {3295, {wxStyledTextCtrl, setViewEOL, 1}},
- {3296, {wxStyledTextCtrl, setModEventMask, 1}},
- {3297, {wxStyledTextCtrl, getEdgeColumn, 0}},
- {3298, {wxStyledTextCtrl, setEdgeColumn, 1}},
- {3299, {wxStyledTextCtrl, setEdgeMode, 1}},
- {3300, {wxStyledTextCtrl, getEdgeMode, 0}},
- {3301, {wxStyledTextCtrl, getEdgeColour, 0}},
- {3302, {wxStyledTextCtrl, setEdgeColour, 1}},
- {3303, {wxStyledTextCtrl, searchAnchor, 0}},
- {3304, {wxStyledTextCtrl, searchNext, 2}},
- {3305, {wxStyledTextCtrl, searchPrev, 2}},
- {3306, {wxStyledTextCtrl, linesOnScreen, 0}},
- {3307, {wxStyledTextCtrl, usePopUp, 1}},
- {3308, {wxStyledTextCtrl, selectionIsRectangle, 0}},
- {3309, {wxStyledTextCtrl, setZoom, 1}},
- {3310, {wxStyledTextCtrl, getZoom, 0}},
- {3311, {wxStyledTextCtrl, getModEventMask, 0}},
- {3312, {wxStyledTextCtrl, setSTCFocus, 1}},
- {3313, {wxStyledTextCtrl, getSTCFocus, 0}},
- {3314, {wxStyledTextCtrl, setStatus, 1}},
- {3315, {wxStyledTextCtrl, getStatus, 0}},
- {3316, {wxStyledTextCtrl, setMouseDownCaptures, 1}},
- {3317, {wxStyledTextCtrl, getMouseDownCaptures, 0}},
- {3318, {wxStyledTextCtrl, setSTCCursor, 1}},
- {3319, {wxStyledTextCtrl, getSTCCursor, 0}},
- {3320, {wxStyledTextCtrl, setControlCharSymbol, 1}},
- {3321, {wxStyledTextCtrl, getControlCharSymbol, 0}},
- {3322, {wxStyledTextCtrl, wordPartLeft, 0}},
- {3323, {wxStyledTextCtrl, wordPartLeftExtend, 0}},
- {3324, {wxStyledTextCtrl, wordPartRight, 0}},
- {3325, {wxStyledTextCtrl, wordPartRightExtend, 0}},
- {3326, {wxStyledTextCtrl, setVisiblePolicy, 2}},
- {3327, {wxStyledTextCtrl, delLineLeft, 0}},
- {3328, {wxStyledTextCtrl, delLineRight, 0}},
- {3329, {wxStyledTextCtrl, getXOffset, 0}},
- {3330, {wxStyledTextCtrl, chooseCaretX, 0}},
- {3331, {wxStyledTextCtrl, setXCaretPolicy, 2}},
- {3332, {wxStyledTextCtrl, setYCaretPolicy, 2}},
- {3333, {wxStyledTextCtrl, getPrintWrapMode, 0}},
- {3334, {wxStyledTextCtrl, setHotspotActiveForeground, 2}},
- {3335, {wxStyledTextCtrl, setHotspotActiveBackground, 2}},
- {3336, {wxStyledTextCtrl, setHotspotActiveUnderline, 1}},
- {3337, {wxStyledTextCtrl, setHotspotSingleLine, 1}},
- {3338, {wxStyledTextCtrl, paraDownExtend, 0}},
- {3339, {wxStyledTextCtrl, paraUp, 0}},
- {3340, {wxStyledTextCtrl, paraUpExtend, 0}},
- {3341, {wxStyledTextCtrl, positionBefore, 1}},
- {3342, {wxStyledTextCtrl, positionAfter, 1}},
- {3343, {wxStyledTextCtrl, copyRange, 2}},
- {3344, {wxStyledTextCtrl, copyText, 2}},
- {3345, {wxStyledTextCtrl, setSelectionMode, 1}},
- {3346, {wxStyledTextCtrl, getSelectionMode, 0}},
- {3347, {wxStyledTextCtrl, lineDownRectExtend, 0}},
- {3348, {wxStyledTextCtrl, lineUpRectExtend, 0}},
- {3349, {wxStyledTextCtrl, charLeftRectExtend, 0}},
- {3350, {wxStyledTextCtrl, charRightRectExtend, 0}},
- {3351, {wxStyledTextCtrl, homeRectExtend, 0}},
- {3352, {wxStyledTextCtrl, vCHomeRectExtend, 0}},
- {3353, {wxStyledTextCtrl, lineEndRectExtend, 0}},
- {3354, {wxStyledTextCtrl, pageUpRectExtend, 0}},
- {3355, {wxStyledTextCtrl, pageDownRectExtend, 0}},
- {3356, {wxStyledTextCtrl, stutteredPageUp, 0}},
- {3357, {wxStyledTextCtrl, stutteredPageUpExtend, 0}},
- {3358, {wxStyledTextCtrl, stutteredPageDown, 0}},
- {3359, {wxStyledTextCtrl, stutteredPageDownExtend, 0}},
- {3360, {wxStyledTextCtrl, wordLeftEnd, 0}},
- {3361, {wxStyledTextCtrl, wordLeftEndExtend, 0}},
- {3362, {wxStyledTextCtrl, wordRightEnd, 0}},
- {3363, {wxStyledTextCtrl, wordRightEndExtend, 0}},
- {3364, {wxStyledTextCtrl, setWhitespaceChars, 1}},
- {3365, {wxStyledTextCtrl, setCharsDefault, 0}},
- {3366, {wxStyledTextCtrl, autoCompGetCurrent, 0}},
- {3367, {wxStyledTextCtrl, allocate, 1}},
- {3368, {wxStyledTextCtrl, findColumn, 2}},
- {3369, {wxStyledTextCtrl, getCaretSticky, 0}},
- {3370, {wxStyledTextCtrl, setCaretSticky, 1}},
- {3371, {wxStyledTextCtrl, toggleCaretSticky, 0}},
- {3372, {wxStyledTextCtrl, setPasteConvertEndings, 1}},
- {3373, {wxStyledTextCtrl, getPasteConvertEndings, 0}},
- {3374, {wxStyledTextCtrl, selectionDuplicate, 0}},
- {3375, {wxStyledTextCtrl, setCaretLineBackAlpha, 1}},
- {3376, {wxStyledTextCtrl, getCaretLineBackAlpha, 0}},
- {3377, {wxStyledTextCtrl, startRecord, 0}},
- {3378, {wxStyledTextCtrl, stopRecord, 0}},
- {3379, {wxStyledTextCtrl, setLexer, 1}},
- {3380, {wxStyledTextCtrl, getLexer, 0}},
- {3381, {wxStyledTextCtrl, colourise, 2}},
- {3382, {wxStyledTextCtrl, setProperty, 2}},
- {3383, {wxStyledTextCtrl, setKeyWords, 2}},
- {3384, {wxStyledTextCtrl, setLexerLanguage, 1}},
- {3385, {wxStyledTextCtrl, getProperty, 1}},
- {3386, {wxStyledTextCtrl, getStyleBitsNeeded, 0}},
- {3387, {wxStyledTextCtrl, getCurrentLine, 0}},
- {3388, {wxStyledTextCtrl, styleSetSpec, 2}},
- {3389, {wxStyledTextCtrl, styleSetFont, 2}},
- {3390, {wxStyledTextCtrl, styleSetFontAttr, 7}},
- {3391, {wxStyledTextCtrl, styleSetCharacterSet, 2}},
- {3392, {wxStyledTextCtrl, styleSetFontEncoding, 2}},
- {3393, {wxStyledTextCtrl, cmdKeyExecute, 1}},
- {3394, {wxStyledTextCtrl, setMargins, 2}},
- {3395, {wxStyledTextCtrl, getSelection, 2}},
- {3396, {wxStyledTextCtrl, pointFromPosition, 1}},
- {3397, {wxStyledTextCtrl, scrollToLine, 1}},
- {3398, {wxStyledTextCtrl, scrollToColumn, 1}},
- {3399, {wxStyledTextCtrl, setVScrollBar, 1}},
- {3400, {wxStyledTextCtrl, setHScrollBar, 1}},
- {3401, {wxStyledTextCtrl, getLastKeydownProcessed, 0}},
- {3402, {wxStyledTextCtrl, setLastKeydownProcessed, 1}},
- {3403, {wxStyledTextCtrl, saveFile, 1}},
- {3404, {wxStyledTextCtrl, loadFile, 1}},
- {3405, {wxStyledTextCtrl, doDragOver, 3}},
- {3406, {wxStyledTextCtrl, doDropText, 3}},
- {3407, {wxStyledTextCtrl, getUseAntiAliasing, 0}},
- {3408, {wxStyledTextCtrl, addTextRaw, 1}},
- {3409, {wxStyledTextCtrl, insertTextRaw, 2}},
- {3410, {wxStyledTextCtrl, getCurLineRaw, 1}},
- {3411, {wxStyledTextCtrl, getLineRaw, 1}},
- {3412, {wxStyledTextCtrl, getSelectedTextRaw, 0}},
- {3413, {wxStyledTextCtrl, getTextRangeRaw, 2}},
- {3414, {wxStyledTextCtrl, setTextRaw, 1}},
- {3415, {wxStyledTextCtrl, getTextRaw, 0}},
- {3416, {wxStyledTextCtrl, appendTextRaw, 1}},
- {3417, {wxArtProvider, getBitmap, 2}},
- {3418, {wxArtProvider, getIcon, 2}},
- {3419, {wxTreeEvent, getKeyCode, 0}},
- {3420, {wxTreeEvent, getItem, 0}},
- {3421, {wxTreeEvent, getKeyEvent, 0}},
- {3422, {wxTreeEvent, getLabel, 0}},
- {3423, {wxTreeEvent, getOldItem, 0}},
- {3424, {wxTreeEvent, getPoint, 0}},
- {3425, {wxTreeEvent, isEditCancelled, 0}},
- {3426, {wxTreeEvent, setToolTip, 1}},
- {3427, {wxNotebookEvent, getOldSelection, 0}},
- {3428, {wxNotebookEvent, getSelection, 0}},
- {3429, {wxNotebookEvent, setOldSelection, 1}},
- {3430, {wxNotebookEvent, setSelection, 1}},
- {3431, {wxFileDataObject, new, 0}},
- {3432, {wxFileDataObject, addFile, 1}},
- {3433, {wxFileDataObject, getFilenames, 0}},
- {3434, {wxFileDataObject, 'Destroy', undefined}},
- {3435, {wxTextDataObject, new, 1}},
- {3436, {wxTextDataObject, getTextLength, 0}},
- {3437, {wxTextDataObject, getText, 0}},
- {3438, {wxTextDataObject, setText, 1}},
- {3439, {wxTextDataObject, 'Destroy', undefined}},
- {3440, {wxBitmapDataObject, new_1_1, 1}},
- {3441, {wxBitmapDataObject, new_1_0, 1}},
- {3442, {wxBitmapDataObject, getBitmap, 0}},
- {3443, {wxBitmapDataObject, setBitmap, 1}},
- {3444, {wxBitmapDataObject, 'Destroy', undefined}},
- {3446, {wxClipboard, new, 0}},
- {3447, {wxClipboard, destruct, 0}},
- {3448, {wxClipboard, addData, 1}},
- {3449, {wxClipboard, clear, 0}},
- {3450, {wxClipboard, close, 0}},
- {3451, {wxClipboard, flush, 0}},
- {3452, {wxClipboard, getData, 1}},
- {3453, {wxClipboard, isOpened, 0}},
- {3454, {wxClipboard, open, 0}},
- {3455, {wxClipboard, setData, 1}},
- {3457, {wxClipboard, usePrimarySelection, 1}},
- {3458, {wxClipboard, isSupported, 1}},
- {3459, {wxClipboard, get, 0}},
- {3460, {wxSpinEvent, getPosition, 0}},
- {3461, {wxSpinEvent, setPosition, 1}},
- {3462, {wxSplitterWindow, new_0, 0}},
- {3463, {wxSplitterWindow, new_2, 2}},
- {3464, {wxSplitterWindow, destruct, 0}},
- {3465, {wxSplitterWindow, create, 2}},
- {3466, {wxSplitterWindow, getMinimumPaneSize, 0}},
- {3467, {wxSplitterWindow, getSashGravity, 0}},
- {3468, {wxSplitterWindow, getSashPosition, 0}},
- {3469, {wxSplitterWindow, getSplitMode, 0}},
- {3470, {wxSplitterWindow, getWindow1, 0}},
- {3471, {wxSplitterWindow, getWindow2, 0}},
- {3472, {wxSplitterWindow, initialize, 1}},
- {3473, {wxSplitterWindow, isSplit, 0}},
- {3474, {wxSplitterWindow, replaceWindow, 2}},
- {3475, {wxSplitterWindow, setSashGravity, 1}},
- {3476, {wxSplitterWindow, setSashPosition, 2}},
- {3477, {wxSplitterWindow, setSashSize, 1}},
- {3478, {wxSplitterWindow, setMinimumPaneSize, 1}},
- {3479, {wxSplitterWindow, setSplitMode, 1}},
- {3480, {wxSplitterWindow, splitHorizontally, 3}},
- {3481, {wxSplitterWindow, splitVertically, 3}},
- {3482, {wxSplitterWindow, unsplit, 1}},
- {3483, {wxSplitterWindow, updateSize, 0}},
- {3484, {wxSplitterEvent, getSashPosition, 0}},
- {3485, {wxSplitterEvent, getX, 0}},
- {3486, {wxSplitterEvent, getY, 0}},
- {3487, {wxSplitterEvent, getWindowBeingRemoved, 0}},
- {3488, {wxSplitterEvent, setSashPosition, 1}},
- {3489, {wxHtmlWindow, new_0, 0}},
- {3490, {wxHtmlWindow, new_2, 2}},
- {3491, {wxHtmlWindow, appendToPage, 1}},
- {3492, {wxHtmlWindow, getOpenedAnchor, 0}},
- {3493, {wxHtmlWindow, getOpenedPage, 0}},
- {3494, {wxHtmlWindow, getOpenedPageTitle, 0}},
- {3495, {wxHtmlWindow, getRelatedFrame, 0}},
- {3496, {wxHtmlWindow, historyBack, 0}},
- {3497, {wxHtmlWindow, historyCanBack, 0}},
- {3498, {wxHtmlWindow, historyCanForward, 0}},
- {3499, {wxHtmlWindow, historyClear, 0}},
- {3500, {wxHtmlWindow, historyForward, 0}},
- {3501, {wxHtmlWindow, loadFile, 1}},
- {3502, {wxHtmlWindow, loadPage, 1}},
- {3503, {wxHtmlWindow, selectAll, 0}},
- {3504, {wxHtmlWindow, selectionToText, 0}},
- {3505, {wxHtmlWindow, selectLine, 1}},
- {3506, {wxHtmlWindow, selectWord, 1}},
- {3507, {wxHtmlWindow, setBorders, 1}},
- {3508, {wxHtmlWindow, setFonts, 3}},
- {3509, {wxHtmlWindow, setPage, 1}},
- {3510, {wxHtmlWindow, setRelatedFrame, 2}},
- {3511, {wxHtmlWindow, setRelatedStatusBar, 1}},
- {3512, {wxHtmlWindow, toText, 0}},
- {3513, {wxHtmlWindow, 'Destroy', undefined}},
- {3514, {wxHtmlLinkEvent, getLinkInfo, 0}},
- {3515, {wxSystemSettings, getColour, 1}},
- {3516, {wxSystemSettings, getFont, 1}},
- {3517, {wxSystemSettings, getMetric, 2}},
- {3518, {wxSystemSettings, getScreenType, 0}},
- {3519, {wxSystemOptions, getOption, 1}},
- {3520, {wxSystemOptions, getOptionInt, 1}},
- {3521, {wxSystemOptions, hasOption, 1}},
- {3522, {wxSystemOptions, isFalse, 1}},
- {3523, {wxSystemOptions, setOption_2_1, 2}},
- {3524, {wxSystemOptions, setOption_2_0, 2}},
- {3525, {wxAuiNotebookEvent, setSelection, 1}},
- {3526, {wxAuiNotebookEvent, getSelection, 0}},
- {3527, {wxAuiNotebookEvent, setOldSelection, 1}},
- {3528, {wxAuiNotebookEvent, getOldSelection, 0}},
- {3529, {wxAuiNotebookEvent, setDragSource, 1}},
- {3530, {wxAuiNotebookEvent, getDragSource, 0}},
- {3531, {wxAuiManagerEvent, setManager, 1}},
- {3532, {wxAuiManagerEvent, getManager, 0}},
- {3533, {wxAuiManagerEvent, setPane, 1}},
- {3534, {wxAuiManagerEvent, getPane, 0}},
- {3535, {wxAuiManagerEvent, setButton, 1}},
- {3536, {wxAuiManagerEvent, getButton, 0}},
- {3537, {wxAuiManagerEvent, setDC, 1}},
- {3538, {wxAuiManagerEvent, getDC, 0}},
- {3539, {wxAuiManagerEvent, veto, 1}},
- {3540, {wxAuiManagerEvent, getVeto, 0}},
- {3541, {wxAuiManagerEvent, setCanVeto, 1}},
- {3542, {wxAuiManagerEvent, canVeto, 0}},
- {3543, {wxLogNull, new, 0}},
- {3544, {wxLogNull, 'Destroy', undefined}},
- {3545, {wxTaskBarIcon, new, 0}},
- {3546, {wxTaskBarIcon, destruct, 0}},
- {3547, {wxTaskBarIcon, popupMenu, 1}},
- {3548, {wxTaskBarIcon, removeIcon, 0}},
- {3549, {wxTaskBarIcon, setIcon, 2}},
- {3550, {wxLocale, new_0, 0}},
- {3552, {wxLocale, new_2, 2}},
- {3553, {wxLocale, destruct, 0}},
- {3555, {wxLocale, init, 1}},
- {3556, {wxLocale, addCatalog_1, 1}},
- {3557, {wxLocale, addCatalog_3, 3}},
- {3558, {wxLocale, addCatalogLookupPathPrefix, 1}},
- {3559, {wxLocale, getCanonicalName, 0}},
- {3560, {wxLocale, getLanguage, 0}},
- {3561, {wxLocale, getLanguageName, 1}},
- {3562, {wxLocale, getLocale, 0}},
- {3563, {wxLocale, getName, 0}},
- {3564, {wxLocale, getString_2, 2}},
- {3565, {wxLocale, getString_4, 4}},
- {3566, {wxLocale, getHeaderValue, 2}},
- {3567, {wxLocale, getSysName, 0}},
- {3568, {wxLocale, getSystemEncoding, 0}},
- {3569, {wxLocale, getSystemEncodingName, 0}},
- {3570, {wxLocale, getSystemLanguage, 0}},
- {3571, {wxLocale, isLoaded, 1}},
- {3572, {wxLocale, isOk, 0}},
- {3573, {wxActivateEvent, getActive, 0}},
- {3575, {wxPopupWindow, new_2, 2}},
- {3576, {wxPopupWindow, new_0, 0}},
- {3578, {wxPopupWindow, destruct, 0}},
- {3579, {wxPopupWindow, create, 2}},
- {3580, {wxPopupWindow, position, 2}},
- {3581, {wxPopupTransientWindow, new_0, 0}},
- {3582, {wxPopupTransientWindow, new_2, 2}},
- {3583, {wxPopupTransientWindow, destruct, 0}},
- {3584, {wxPopupTransientWindow, popup, 1}},
- {3585, {wxPopupTransientWindow, dismiss, 0}},
+ {984, {wxToolBar, addStretchableSpace, 0}},
+ {985, {wxToolBar, insertStretchableSpace, 1}},
+ {986, {wxToolBar, deleteTool, 1}},
+ {987, {wxToolBar, deleteToolByPos, 1}},
+ {988, {wxToolBar, enableTool, 2}},
+ {989, {wxToolBar, findById, 1}},
+ {990, {wxToolBar, findControl, 1}},
+ {991, {wxToolBar, findToolForPosition, 2}},
+ {992, {wxToolBar, getToolSize, 0}},
+ {993, {wxToolBar, getToolBitmapSize, 0}},
+ {994, {wxToolBar, getMargins, 0}},
+ {995, {wxToolBar, getToolEnabled, 1}},
+ {996, {wxToolBar, getToolLongHelp, 1}},
+ {997, {wxToolBar, getToolPacking, 0}},
+ {998, {wxToolBar, getToolPos, 1}},
+ {999, {wxToolBar, getToolSeparation, 0}},
+ {1000, {wxToolBar, getToolShortHelp, 1}},
+ {1001, {wxToolBar, getToolState, 1}},
+ {1002, {wxToolBar, insertControl, 2}},
+ {1003, {wxToolBar, insertSeparator, 1}},
+ {1004, {wxToolBar, insertTool_5, 5}},
+ {1005, {wxToolBar, insertTool_2, 2}},
+ {1006, {wxToolBar, insertTool_4, 4}},
+ {1007, {wxToolBar, realize, 0}},
+ {1008, {wxToolBar, removeTool, 1}},
+ {1009, {wxToolBar, setMargins, 2}},
+ {1010, {wxToolBar, setToolBitmapSize, 1}},
+ {1011, {wxToolBar, setToolLongHelp, 2}},
+ {1012, {wxToolBar, setToolPacking, 1}},
+ {1013, {wxToolBar, setToolShortHelp, 2}},
+ {1014, {wxToolBar, setToolSeparation, 1}},
+ {1015, {wxToolBar, toggleTool, 2}},
+ {1017, {wxStatusBar, new_0, 0}},
+ {1018, {wxStatusBar, new_2, 2}},
+ {1020, {wxStatusBar, destruct, 0}},
+ {1021, {wxStatusBar, create, 2}},
+ {1022, {wxStatusBar, getFieldRect, 2}},
+ {1023, {wxStatusBar, getFieldsCount, 0}},
+ {1024, {wxStatusBar, getStatusText, 1}},
+ {1025, {wxStatusBar, popStatusText, 1}},
+ {1026, {wxStatusBar, pushStatusText, 2}},
+ {1027, {wxStatusBar, setFieldsCount, 2}},
+ {1028, {wxStatusBar, setMinHeight, 1}},
+ {1029, {wxStatusBar, setStatusText, 2}},
+ {1030, {wxStatusBar, setStatusWidths, 2}},
+ {1031, {wxStatusBar, setStatusStyles, 2}},
+ {1032, {wxBitmap, new_0, 0}},
+ {1033, {wxBitmap, new_3, 3}},
+ {1034, {wxBitmap, new_4, 4}},
+ {1035, {wxBitmap, new_2_0, 2}},
+ {1036, {wxBitmap, new_2_1, 2}},
+ {1037, {wxBitmap, destruct, 0}},
+ {1038, {wxBitmap, convertToImage, 0}},
+ {1039, {wxBitmap, copyFromIcon, 1}},
+ {1040, {wxBitmap, create, 3}},
+ {1041, {wxBitmap, getDepth, 0}},
+ {1042, {wxBitmap, getHeight, 0}},
+ {1043, {wxBitmap, getPalette, 0}},
+ {1044, {wxBitmap, getMask, 0}},
+ {1045, {wxBitmap, getWidth, 0}},
+ {1046, {wxBitmap, getSubBitmap, 1}},
+ {1047, {wxBitmap, loadFile, 2}},
+ {1048, {wxBitmap, ok, 0}},
+ {1049, {wxBitmap, saveFile, 3}},
+ {1050, {wxBitmap, setDepth, 1}},
+ {1051, {wxBitmap, setHeight, 1}},
+ {1052, {wxBitmap, setMask, 1}},
+ {1053, {wxBitmap, setPalette, 1}},
+ {1054, {wxBitmap, setWidth, 1}},
+ {1055, {wxIcon, new_0, 0}},
+ {1056, {wxIcon, new_2, 2}},
+ {1057, {wxIcon, new_1, 1}},
+ {1058, {wxIcon, copyFromBitmap, 1}},
+ {1059, {wxIcon, 'Destroy', undefined}},
+ {1060, {wxIconBundle, new_0, 0}},
+ {1061, {wxIconBundle, new_2, 2}},
+ {1062, {wxIconBundle, new_1_0, 1}},
+ {1063, {wxIconBundle, new_1_1, 1}},
+ {1064, {wxIconBundle, destruct, 0}},
+ {1065, {wxIconBundle, addIcon_2, 2}},
+ {1066, {wxIconBundle, addIcon_1, 1}},
+ {1067, {wxIconBundle, getIcon_1_1, 1}},
+ {1068, {wxIconBundle, getIcon_1_0, 1}},
+ {1069, {wxCursor, new_0, 0}},
+ {1070, {wxCursor, new_1_0, 1}},
+ {1071, {wxCursor, new_1_1, 1}},
+ {1072, {wxCursor, new_4, 4}},
+ {1073, {wxCursor, destruct, 0}},
+ {1074, {wxCursor, ok, 0}},
+ {1075, {wxMask, new_0, 0}},
+ {1076, {wxMask, new_2_1, 2}},
+ {1077, {wxMask, new_2_0, 2}},
+ {1078, {wxMask, new_1, 1}},
+ {1079, {wxMask, destruct, 0}},
+ {1080, {wxMask, create_2_1, 2}},
+ {1081, {wxMask, create_2_0, 2}},
+ {1082, {wxMask, create_1, 1}},
+ {1083, {wxImage, new_0, 0}},
+ {1084, {wxImage, new_3_0, 3}},
+ {1085, {wxImage, new_4, 4}},
+ {1086, {wxImage, new_5, 5}},
+ {1087, {wxImage, new_2, 2}},
+ {1088, {wxImage, new_3_1, 3}},
+ {1089, {wxImage, blur, 1}},
+ {1090, {wxImage, blurHorizontal, 1}},
+ {1091, {wxImage, blurVertical, 1}},
+ {1092, {wxImage, convertAlphaToMask, 1}},
+ {1093, {wxImage, convertToGreyscale, 1}},
+ {1094, {wxImage, convertToMono, 3}},
+ {1095, {wxImage, copy, 0}},
+ {1096, {wxImage, create_3, 3}},
+ {1097, {wxImage, create_4, 4}},
+ {1098, {wxImage, create_5, 5}},
+ {1099, {wxImage, 'Destroy', 0}},
+ {1100, {wxImage, findFirstUnusedColour, 4}},
+ {1101, {wxImage, getImageExtWildcard, 0}},
+ {1102, {wxImage, getAlpha_2, 2}},
+ {1103, {wxImage, getAlpha_0, 0}},
+ {1104, {wxImage, getBlue, 2}},
+ {1105, {wxImage, getData, 0}},
+ {1106, {wxImage, getGreen, 2}},
+ {1107, {wxImage, getImageCount, 2}},
+ {1108, {wxImage, getHeight, 0}},
+ {1109, {wxImage, getMaskBlue, 0}},
+ {1110, {wxImage, getMaskGreen, 0}},
+ {1111, {wxImage, getMaskRed, 0}},
+ {1112, {wxImage, getOrFindMaskColour, 3}},
+ {1113, {wxImage, getPalette, 0}},
+ {1114, {wxImage, getRed, 2}},
+ {1115, {wxImage, getSubImage, 1}},
+ {1116, {wxImage, getWidth, 0}},
+ {1117, {wxImage, hasAlpha, 0}},
+ {1118, {wxImage, hasMask, 0}},
+ {1119, {wxImage, getOption, 1}},
+ {1120, {wxImage, getOptionInt, 1}},
+ {1121, {wxImage, hasOption, 1}},
+ {1122, {wxImage, initAlpha, 0}},
+ {1123, {wxImage, initStandardHandlers, 0}},
+ {1124, {wxImage, isTransparent, 3}},
+ {1125, {wxImage, loadFile_2, 2}},
+ {1126, {wxImage, loadFile_3, 3}},
+ {1127, {wxImage, ok, 0}},
+ {1128, {wxImage, removeHandler, 1}},
+ {1129, {wxImage, mirror, 1}},
+ {1130, {wxImage, replace, 6}},
+ {1131, {wxImage, rescale, 3}},
+ {1132, {wxImage, resize, 3}},
+ {1133, {wxImage, rotate, 3}},
+ {1134, {wxImage, rotateHue, 1}},
+ {1135, {wxImage, rotate90, 1}},
+ {1136, {wxImage, saveFile_1, 1}},
+ {1137, {wxImage, saveFile_2_0, 2}},
+ {1138, {wxImage, saveFile_2_1, 2}},
+ {1139, {wxImage, scale, 3}},
+ {1140, {wxImage, size, 3}},
+ {1141, {wxImage, setAlpha_3, 3}},
+ {1142, {wxImage, setAlpha_2, 2}},
+ {1143, {wxImage, setData_2, 2}},
+ {1144, {wxImage, setData_4, 4}},
+ {1145, {wxImage, setMask, 1}},
+ {1146, {wxImage, setMaskColour, 3}},
+ {1147, {wxImage, setMaskFromImage, 4}},
+ {1148, {wxImage, setOption_2_1, 2}},
+ {1149, {wxImage, setOption_2_0, 2}},
+ {1150, {wxImage, setPalette, 1}},
+ {1151, {wxImage, setRGB_5, 5}},
+ {1152, {wxImage, setRGB_4, 4}},
+ {1153, {wxImage, 'Destroy', undefined}},
+ {1154, {wxBrush, new_0, 0}},
+ {1155, {wxBrush, new_2, 2}},
+ {1156, {wxBrush, new_1, 1}},
+ {1158, {wxBrush, destruct, 0}},
+ {1159, {wxBrush, getColour, 0}},
+ {1160, {wxBrush, getStipple, 0}},
+ {1161, {wxBrush, getStyle, 0}},
+ {1162, {wxBrush, isHatch, 0}},
+ {1163, {wxBrush, isOk, 0}},
+ {1164, {wxBrush, setColour_1, 1}},
+ {1165, {wxBrush, setColour_3, 3}},
+ {1166, {wxBrush, setStipple, 1}},
+ {1167, {wxBrush, setStyle, 1}},
+ {1168, {wxPen, new_0, 0}},
+ {1169, {wxPen, new_2, 2}},
+ {1170, {wxPen, destruct, 0}},
+ {1171, {wxPen, getCap, 0}},
+ {1172, {wxPen, getColour, 0}},
+ {1173, {wxPen, getJoin, 0}},
+ {1174, {wxPen, getStyle, 0}},
+ {1175, {wxPen, getWidth, 0}},
+ {1176, {wxPen, isOk, 0}},
+ {1177, {wxPen, setCap, 1}},
+ {1178, {wxPen, setColour_1, 1}},
+ {1179, {wxPen, setColour_3, 3}},
+ {1180, {wxPen, setJoin, 1}},
+ {1181, {wxPen, setStyle, 1}},
+ {1182, {wxPen, setWidth, 1}},
+ {1183, {wxRegion, new_0, 0}},
+ {1184, {wxRegion, new_4, 4}},
+ {1185, {wxRegion, new_2, 2}},
+ {1186, {wxRegion, new_1_1, 1}},
+ {1188, {wxRegion, new_1_0, 1}},
+ {1190, {wxRegion, destruct, 0}},
+ {1191, {wxRegion, clear, 0}},
+ {1192, {wxRegion, contains_2, 2}},
+ {1193, {wxRegion, contains_1_0, 1}},
+ {1194, {wxRegion, contains_4, 4}},
+ {1195, {wxRegion, contains_1_1, 1}},
+ {1196, {wxRegion, convertToBitmap, 0}},
+ {1197, {wxRegion, getBox, 0}},
+ {1198, {wxRegion, intersect_4, 4}},
+ {1199, {wxRegion, intersect_1_1, 1}},
+ {1200, {wxRegion, intersect_1_0, 1}},
+ {1201, {wxRegion, isEmpty, 0}},
+ {1202, {wxRegion, subtract_4, 4}},
+ {1203, {wxRegion, subtract_1_1, 1}},
+ {1204, {wxRegion, subtract_1_0, 1}},
+ {1205, {wxRegion, offset_2, 2}},
+ {1206, {wxRegion, offset_1, 1}},
+ {1207, {wxRegion, union_4, 4}},
+ {1208, {wxRegion, union_1_2, 1}},
+ {1209, {wxRegion, union_1_1, 1}},
+ {1210, {wxRegion, union_1_0, 1}},
+ {1211, {wxRegion, union_3, 3}},
+ {1212, {wxRegion, xor_4, 4}},
+ {1213, {wxRegion, xor_1_1, 1}},
+ {1214, {wxRegion, xor_1_0, 1}},
+ {1215, {wxAcceleratorTable, new_0, 0}},
+ {1216, {wxAcceleratorTable, new_2, 2}},
+ {1217, {wxAcceleratorTable, destruct, 0}},
+ {1218, {wxAcceleratorTable, ok, 0}},
+ {1219, {wxAcceleratorEntry, new_1_0, 1}},
+ {1220, {wxAcceleratorEntry, new_1_1, 1}},
+ {1221, {wxAcceleratorEntry, getCommand, 0}},
+ {1222, {wxAcceleratorEntry, getFlags, 0}},
+ {1223, {wxAcceleratorEntry, getKeyCode, 0}},
+ {1224, {wxAcceleratorEntry, set, 4}},
+ {1225, {wxAcceleratorEntry, 'Destroy', undefined}},
+ {1230, {wxCaret, new_3, 3}},
+ {1231, {wxCaret, new_2, 2}},
+ {1233, {wxCaret, destruct, 0}},
+ {1234, {wxCaret, create_3, 3}},
+ {1235, {wxCaret, create_2, 2}},
+ {1236, {wxCaret, getBlinkTime, 0}},
+ {1238, {wxCaret, getPosition, 0}},
+ {1240, {wxCaret, getSize, 0}},
+ {1241, {wxCaret, getWindow, 0}},
+ {1242, {wxCaret, hide, 0}},
+ {1243, {wxCaret, isOk, 0}},
+ {1244, {wxCaret, isVisible, 0}},
+ {1245, {wxCaret, move_2, 2}},
+ {1246, {wxCaret, move_1, 1}},
+ {1247, {wxCaret, setBlinkTime, 1}},
+ {1248, {wxCaret, setSize_2, 2}},
+ {1249, {wxCaret, setSize_1, 1}},
+ {1250, {wxCaret, show, 1}},
+ {1251, {wxSizer, add_2_1, 2}},
+ {1252, {wxSizer, add_2_0, 2}},
+ {1253, {wxSizer, add_3, 3}},
+ {1254, {wxSizer, add_2_3, 2}},
+ {1255, {wxSizer, add_2_2, 2}},
+ {1256, {wxSizer, addSpacer, 1}},
+ {1257, {wxSizer, addStretchSpacer, 1}},
+ {1258, {wxSizer, calcMin, 0}},
+ {1259, {wxSizer, clear, 1}},
+ {1260, {wxSizer, detach_1_2, 1}},
+ {1261, {wxSizer, detach_1_1, 1}},
+ {1262, {wxSizer, detach_1_0, 1}},
+ {1263, {wxSizer, fit, 1}},
+ {1264, {wxSizer, fitInside, 1}},
+ {1265, {wxSizer, getChildren, 0}},
+ {1266, {wxSizer, getItem_2_1, 2}},
+ {1267, {wxSizer, getItem_2_0, 2}},
+ {1268, {wxSizer, getItem_1, 1}},
+ {1269, {wxSizer, getSize, 0}},
+ {1270, {wxSizer, getPosition, 0}},
+ {1271, {wxSizer, getMinSize, 0}},
+ {1272, {wxSizer, hide_2_0, 2}},
+ {1273, {wxSizer, hide_2_1, 2}},
+ {1274, {wxSizer, hide_1, 1}},
+ {1275, {wxSizer, insert_3_1, 3}},
+ {1276, {wxSizer, insert_3_0, 3}},
+ {1277, {wxSizer, insert_4, 4}},
+ {1278, {wxSizer, insert_3_3, 3}},
+ {1279, {wxSizer, insert_3_2, 3}},
+ {1280, {wxSizer, insert_2, 2}},
+ {1281, {wxSizer, insertSpacer, 2}},
+ {1282, {wxSizer, insertStretchSpacer, 2}},
+ {1283, {wxSizer, isShown_1_2, 1}},
+ {1284, {wxSizer, isShown_1_1, 1}},
+ {1285, {wxSizer, isShown_1_0, 1}},
+ {1286, {wxSizer, layout, 0}},
+ {1287, {wxSizer, prepend_2_1, 2}},
+ {1288, {wxSizer, prepend_2_0, 2}},
+ {1289, {wxSizer, prepend_3, 3}},
+ {1290, {wxSizer, prepend_2_3, 2}},
+ {1291, {wxSizer, prepend_2_2, 2}},
+ {1292, {wxSizer, prepend_1, 1}},
+ {1293, {wxSizer, prependSpacer, 1}},
+ {1294, {wxSizer, prependStretchSpacer, 1}},
+ {1295, {wxSizer, recalcSizes, 0}},
+ {1296, {wxSizer, remove_1_1, 1}},
+ {1297, {wxSizer, remove_1_0, 1}},
+ {1298, {wxSizer, replace_3_1, 3}},
+ {1299, {wxSizer, replace_3_0, 3}},
+ {1300, {wxSizer, replace_2, 2}},
+ {1301, {wxSizer, setDimension, 4}},
+ {1302, {wxSizer, setMinSize_2, 2}},
+ {1303, {wxSizer, setMinSize_1, 1}},
+ {1304, {wxSizer, setItemMinSize_3_2, 3}},
+ {1305, {wxSizer, setItemMinSize_2_2, 2}},
+ {1306, {wxSizer, setItemMinSize_3_1, 3}},
+ {1307, {wxSizer, setItemMinSize_2_1, 2}},
+ {1308, {wxSizer, setItemMinSize_3_0, 3}},
+ {1309, {wxSizer, setItemMinSize_2_0, 2}},
+ {1310, {wxSizer, setSizeHints, 1}},
+ {1311, {wxSizer, setVirtualSizeHints, 1}},
+ {1312, {wxSizer, show_2_2, 2}},
+ {1313, {wxSizer, show_2_1, 2}},
+ {1314, {wxSizer, show_2_0, 2}},
+ {1315, {wxSizer, show_1, 1}},
+ {1316, {wxSizerFlags, new, 1}},
+ {1317, {wxSizerFlags, align, 1}},
+ {1318, {wxSizerFlags, border_2, 2}},
+ {1319, {wxSizerFlags, border_1, 1}},
+ {1320, {wxSizerFlags, center, 0}},
+ {1321, {wxSizerFlags, centre, 0}},
+ {1322, {wxSizerFlags, expand, 0}},
+ {1323, {wxSizerFlags, left, 0}},
+ {1324, {wxSizerFlags, proportion, 1}},
+ {1325, {wxSizerFlags, right, 0}},
+ {1326, {wxSizerFlags, 'Destroy', undefined}},
+ {1327, {wxSizerItem, new_5_1, 5}},
+ {1328, {wxSizerItem, new_2_1, 2}},
+ {1329, {wxSizerItem, new_5_0, 5}},
+ {1330, {wxSizerItem, new_2_0, 2}},
+ {1331, {wxSizerItem, new_6, 6}},
+ {1332, {wxSizerItem, new_3, 3}},
+ {1333, {wxSizerItem, new_0, 0}},
+ {1334, {wxSizerItem, destruct, 0}},
+ {1335, {wxSizerItem, calcMin, 0}},
+ {1336, {wxSizerItem, deleteWindows, 0}},
+ {1337, {wxSizerItem, detachSizer, 0}},
+ {1338, {wxSizerItem, getBorder, 0}},
+ {1339, {wxSizerItem, getFlag, 0}},
+ {1340, {wxSizerItem, getMinSize, 0}},
+ {1341, {wxSizerItem, getPosition, 0}},
+ {1342, {wxSizerItem, getProportion, 0}},
+ {1343, {wxSizerItem, getRatio, 0}},
+ {1344, {wxSizerItem, getRect, 0}},
+ {1345, {wxSizerItem, getSize, 0}},
+ {1346, {wxSizerItem, getSizer, 0}},
+ {1347, {wxSizerItem, getSpacer, 0}},
+ {1348, {wxSizerItem, getUserData, 0}},
+ {1349, {wxSizerItem, getWindow, 0}},
+ {1350, {wxSizerItem, isSizer, 0}},
+ {1351, {wxSizerItem, isShown, 0}},
+ {1352, {wxSizerItem, isSpacer, 0}},
+ {1353, {wxSizerItem, isWindow, 0}},
+ {1354, {wxSizerItem, setBorder, 1}},
+ {1355, {wxSizerItem, setDimension, 2}},
+ {1356, {wxSizerItem, setFlag, 1}},
+ {1357, {wxSizerItem, setInitSize, 2}},
+ {1358, {wxSizerItem, setMinSize_1, 1}},
+ {1359, {wxSizerItem, setMinSize_2, 2}},
+ {1360, {wxSizerItem, setProportion, 1}},
+ {1361, {wxSizerItem, setRatio_2, 2}},
+ {1362, {wxSizerItem, setRatio_1_1, 1}},
+ {1363, {wxSizerItem, setRatio_1_0, 1}},
+ {1364, {wxSizerItem, setSizer, 1}},
+ {1365, {wxSizerItem, setSpacer_1, 1}},
+ {1366, {wxSizerItem, setSpacer_2, 2}},
+ {1367, {wxSizerItem, setWindow, 1}},
+ {1368, {wxSizerItem, show, 1}},
+ {1369, {wxBoxSizer, new, 1}},
+ {1370, {wxBoxSizer, getOrientation, 0}},
+ {1371, {wxBoxSizer, 'Destroy', undefined}},
+ {1372, {wxStaticBoxSizer, new_2, 2}},
+ {1373, {wxStaticBoxSizer, new_3, 3}},
+ {1374, {wxStaticBoxSizer, getStaticBox, 0}},
+ {1375, {wxStaticBoxSizer, 'Destroy', undefined}},
+ {1376, {wxGridSizer, new_4, 4}},
+ {1377, {wxGridSizer, new_2, 2}},
+ {1378, {wxGridSizer, getCols, 0}},
+ {1379, {wxGridSizer, getHGap, 0}},
+ {1380, {wxGridSizer, getRows, 0}},
+ {1381, {wxGridSizer, getVGap, 0}},
+ {1382, {wxGridSizer, setCols, 1}},
+ {1383, {wxGridSizer, setHGap, 1}},
+ {1384, {wxGridSizer, setRows, 1}},
+ {1385, {wxGridSizer, setVGap, 1}},
+ {1386, {wxGridSizer, 'Destroy', undefined}},
+ {1387, {wxFlexGridSizer, new_4, 4}},
+ {1388, {wxFlexGridSizer, new_2, 2}},
+ {1389, {wxFlexGridSizer, addGrowableCol, 2}},
+ {1390, {wxFlexGridSizer, addGrowableRow, 2}},
+ {1391, {wxFlexGridSizer, getFlexibleDirection, 0}},
+ {1392, {wxFlexGridSizer, getNonFlexibleGrowMode, 0}},
+ {1393, {wxFlexGridSizer, removeGrowableCol, 1}},
+ {1394, {wxFlexGridSizer, removeGrowableRow, 1}},
+ {1395, {wxFlexGridSizer, setFlexibleDirection, 1}},
+ {1396, {wxFlexGridSizer, setNonFlexibleGrowMode, 1}},
+ {1397, {wxFlexGridSizer, 'Destroy', undefined}},
+ {1398, {wxGridBagSizer, new, 1}},
+ {1399, {wxGridBagSizer, add_3_2, 3}},
+ {1400, {wxGridBagSizer, add_3_1, 3}},
+ {1401, {wxGridBagSizer, add_4, 4}},
+ {1402, {wxGridBagSizer, add_1_0, 1}},
+ {1403, {wxGridBagSizer, add_2_1, 2}},
+ {1404, {wxGridBagSizer, add_2_0, 2}},
+ {1405, {wxGridBagSizer, add_3_0, 3}},
+ {1406, {wxGridBagSizer, add_1_1, 1}},
+ {1407, {wxGridBagSizer, calcMin, 0}},
+ {1408, {wxGridBagSizer, checkForIntersection_2, 2}},
+ {1409, {wxGridBagSizer, checkForIntersection_3, 3}},
+ {1410, {wxGridBagSizer, findItem_1_1, 1}},
+ {1411, {wxGridBagSizer, findItem_1_0, 1}},
+ {1412, {wxGridBagSizer, findItemAtPoint, 1}},
+ {1413, {wxGridBagSizer, findItemAtPosition, 1}},
+ {1414, {wxGridBagSizer, findItemWithData, 1}},
+ {1415, {wxGridBagSizer, getCellSize, 2}},
+ {1416, {wxGridBagSizer, getEmptyCellSize, 0}},
+ {1417, {wxGridBagSizer, getItemPosition_1_2, 1}},
+ {1418, {wxGridBagSizer, getItemPosition_1_1, 1}},
+ {1419, {wxGridBagSizer, getItemPosition_1_0, 1}},
+ {1420, {wxGridBagSizer, getItemSpan_1_2, 1}},
+ {1421, {wxGridBagSizer, getItemSpan_1_1, 1}},
+ {1422, {wxGridBagSizer, getItemSpan_1_0, 1}},
+ {1423, {wxGridBagSizer, setEmptyCellSize, 1}},
+ {1424, {wxGridBagSizer, setItemPosition_2_2, 2}},
+ {1425, {wxGridBagSizer, setItemPosition_2_1, 2}},
+ {1426, {wxGridBagSizer, setItemPosition_2_0, 2}},
+ {1427, {wxGridBagSizer, setItemSpan_2_2, 2}},
+ {1428, {wxGridBagSizer, setItemSpan_2_1, 2}},
+ {1429, {wxGridBagSizer, setItemSpan_2_0, 2}},
+ {1430, {wxGridBagSizer, 'Destroy', undefined}},
+ {1431, {wxStdDialogButtonSizer, new, 0}},
+ {1432, {wxStdDialogButtonSizer, addButton, 1}},
+ {1433, {wxStdDialogButtonSizer, realize, 0}},
+ {1434, {wxStdDialogButtonSizer, setAffirmativeButton, 1}},
+ {1435, {wxStdDialogButtonSizer, setCancelButton, 1}},
+ {1436, {wxStdDialogButtonSizer, setNegativeButton, 1}},
+ {1437, {wxStdDialogButtonSizer, 'Destroy', undefined}},
+ {1438, {wxFont, new_0, 0}},
+ {1439, {wxFont, new_1, 1}},
+ {1440, {wxFont, new_5, 5}},
+ {1442, {wxFont, destruct, 0}},
+ {1443, {wxFont, isFixedWidth, 0}},
+ {1444, {wxFont, getDefaultEncoding, 0}},
+ {1445, {wxFont, getFaceName, 0}},
+ {1446, {wxFont, getFamily, 0}},
+ {1447, {wxFont, getNativeFontInfoDesc, 0}},
+ {1448, {wxFont, getNativeFontInfoUserDesc, 0}},
+ {1449, {wxFont, getPointSize, 0}},
+ {1450, {wxFont, getStyle, 0}},
+ {1451, {wxFont, getUnderlined, 0}},
+ {1452, {wxFont, getWeight, 0}},
+ {1453, {wxFont, ok, 0}},
+ {1454, {wxFont, setDefaultEncoding, 1}},
+ {1455, {wxFont, setFaceName, 1}},
+ {1456, {wxFont, setFamily, 1}},
+ {1457, {wxFont, setPointSize, 1}},
+ {1458, {wxFont, setStyle, 1}},
+ {1459, {wxFont, setUnderlined, 1}},
+ {1460, {wxFont, setWeight, 1}},
+ {1461, {wxToolTip, enable, 1}},
+ {1462, {wxToolTip, setDelay, 1}},
+ {1463, {wxToolTip, new, 1}},
+ {1464, {wxToolTip, setTip, 1}},
+ {1465, {wxToolTip, getTip, 0}},
+ {1466, {wxToolTip, getWindow, 0}},
+ {1467, {wxToolTip, 'Destroy', undefined}},
+ {1469, {wxButton, new_3, 3}},
+ {1470, {wxButton, new_0, 0}},
+ {1471, {wxButton, destruct, 0}},
+ {1472, {wxButton, create, 3}},
+ {1473, {wxButton, getDefaultSize, 0}},
+ {1474, {wxButton, setDefault, 0}},
+ {1475, {wxButton, setLabel, 1}},
+ {1477, {wxBitmapButton, new_4, 4}},
+ {1478, {wxBitmapButton, new_0, 0}},
+ {1479, {wxBitmapButton, create, 4}},
+ {1480, {wxBitmapButton, getBitmapDisabled, 0}},
+ {1482, {wxBitmapButton, getBitmapFocus, 0}},
+ {1484, {wxBitmapButton, getBitmapLabel, 0}},
+ {1486, {wxBitmapButton, getBitmapSelected, 0}},
+ {1488, {wxBitmapButton, setBitmapDisabled, 1}},
+ {1489, {wxBitmapButton, setBitmapFocus, 1}},
+ {1490, {wxBitmapButton, setBitmapLabel, 1}},
+ {1491, {wxBitmapButton, setBitmapSelected, 1}},
+ {1492, {wxBitmapButton, 'Destroy', undefined}},
+ {1493, {wxToggleButton, new_0, 0}},
+ {1494, {wxToggleButton, new_4, 4}},
+ {1495, {wxToggleButton, create, 4}},
+ {1496, {wxToggleButton, getValue, 0}},
+ {1497, {wxToggleButton, setValue, 1}},
+ {1498, {wxToggleButton, 'Destroy', undefined}},
+ {1499, {wxCalendarCtrl, new_0, 0}},
+ {1500, {wxCalendarCtrl, new_3, 3}},
+ {1501, {wxCalendarCtrl, create, 3}},
+ {1502, {wxCalendarCtrl, destruct, 0}},
+ {1503, {wxCalendarCtrl, setDate, 1}},
+ {1504, {wxCalendarCtrl, getDate, 0}},
+ {1505, {wxCalendarCtrl, enableYearChange, 1}},
+ {1506, {wxCalendarCtrl, enableMonthChange, 1}},
+ {1507, {wxCalendarCtrl, enableHolidayDisplay, 1}},
+ {1508, {wxCalendarCtrl, setHeaderColours, 2}},
+ {1509, {wxCalendarCtrl, getHeaderColourFg, 0}},
+ {1510, {wxCalendarCtrl, getHeaderColourBg, 0}},
+ {1511, {wxCalendarCtrl, setHighlightColours, 2}},
+ {1512, {wxCalendarCtrl, getHighlightColourFg, 0}},
+ {1513, {wxCalendarCtrl, getHighlightColourBg, 0}},
+ {1514, {wxCalendarCtrl, setHolidayColours, 2}},
+ {1515, {wxCalendarCtrl, getHolidayColourFg, 0}},
+ {1516, {wxCalendarCtrl, getHolidayColourBg, 0}},
+ {1517, {wxCalendarCtrl, getAttr, 1}},
+ {1518, {wxCalendarCtrl, setAttr, 2}},
+ {1519, {wxCalendarCtrl, setHoliday, 1}},
+ {1520, {wxCalendarCtrl, resetAttr, 1}},
+ {1521, {wxCalendarCtrl, hitTest, 2}},
+ {1522, {wxCalendarDateAttr, new_0, 0}},
+ {1523, {wxCalendarDateAttr, new_2_1, 2}},
+ {1524, {wxCalendarDateAttr, new_2_0, 2}},
+ {1525, {wxCalendarDateAttr, setTextColour, 1}},
+ {1526, {wxCalendarDateAttr, setBackgroundColour, 1}},
+ {1527, {wxCalendarDateAttr, setBorderColour, 1}},
+ {1528, {wxCalendarDateAttr, setFont, 1}},
+ {1529, {wxCalendarDateAttr, setBorder, 1}},
+ {1530, {wxCalendarDateAttr, setHoliday, 1}},
+ {1531, {wxCalendarDateAttr, hasTextColour, 0}},
+ {1532, {wxCalendarDateAttr, hasBackgroundColour, 0}},
+ {1533, {wxCalendarDateAttr, hasBorderColour, 0}},
+ {1534, {wxCalendarDateAttr, hasFont, 0}},
+ {1535, {wxCalendarDateAttr, hasBorder, 0}},
+ {1536, {wxCalendarDateAttr, isHoliday, 0}},
+ {1537, {wxCalendarDateAttr, getTextColour, 0}},
+ {1538, {wxCalendarDateAttr, getBackgroundColour, 0}},
+ {1539, {wxCalendarDateAttr, getBorderColour, 0}},
+ {1540, {wxCalendarDateAttr, getFont, 0}},
+ {1541, {wxCalendarDateAttr, getBorder, 0}},
+ {1542, {wxCalendarDateAttr, 'Destroy', undefined}},
+ {1544, {wxCheckBox, new_4, 4}},
+ {1545, {wxCheckBox, new_0, 0}},
+ {1546, {wxCheckBox, create, 4}},
+ {1547, {wxCheckBox, getValue, 0}},
+ {1548, {wxCheckBox, get3StateValue, 0}},
+ {1549, {wxCheckBox, is3rdStateAllowedForUser, 0}},
+ {1550, {wxCheckBox, is3State, 0}},
+ {1551, {wxCheckBox, isChecked, 0}},
+ {1552, {wxCheckBox, setValue, 1}},
+ {1553, {wxCheckBox, set3StateValue, 1}},
+ {1554, {wxCheckBox, 'Destroy', undefined}},
+ {1555, {wxCheckListBox, new_0, 0}},
+ {1557, {wxCheckListBox, new_3, 3}},
+ {1558, {wxCheckListBox, check, 2}},
+ {1559, {wxCheckListBox, isChecked, 1}},
+ {1560, {wxCheckListBox, 'Destroy', undefined}},
+ {1563, {wxChoice, new_3, 3}},
+ {1564, {wxChoice, new_0, 0}},
+ {1566, {wxChoice, destruct, 0}},
+ {1568, {wxChoice, create, 6}},
+ {1569, {wxChoice, delete, 1}},
+ {1570, {wxChoice, getColumns, 0}},
+ {1571, {wxChoice, setColumns, 1}},
+ {1572, {wxComboBox, new_0, 0}},
+ {1574, {wxComboBox, new_3, 3}},
+ {1575, {wxComboBox, destruct, 0}},
+ {1577, {wxComboBox, create, 7}},
+ {1578, {wxComboBox, canCopy, 0}},
+ {1579, {wxComboBox, canCut, 0}},
+ {1580, {wxComboBox, canPaste, 0}},
+ {1581, {wxComboBox, canRedo, 0}},
+ {1582, {wxComboBox, canUndo, 0}},
+ {1583, {wxComboBox, copy, 0}},
+ {1584, {wxComboBox, cut, 0}},
+ {1585, {wxComboBox, getInsertionPoint, 0}},
+ {1586, {wxComboBox, getLastPosition, 0}},
+ {1587, {wxComboBox, getValue, 0}},
+ {1588, {wxComboBox, paste, 0}},
+ {1589, {wxComboBox, redo, 0}},
+ {1590, {wxComboBox, replace, 3}},
+ {1591, {wxComboBox, remove, 2}},
+ {1592, {wxComboBox, setInsertionPoint, 1}},
+ {1593, {wxComboBox, setInsertionPointEnd, 0}},
+ {1594, {wxComboBox, setSelection_1, 1}},
+ {1595, {wxComboBox, setSelection_2, 2}},
+ {1596, {wxComboBox, setValue, 1}},
+ {1597, {wxComboBox, undo, 0}},
+ {1598, {wxGauge, new_0, 0}},
+ {1599, {wxGauge, new_4, 4}},
+ {1600, {wxGauge, create, 4}},
+ {1601, {wxGauge, getBezelFace, 0}},
+ {1602, {wxGauge, getRange, 0}},
+ {1603, {wxGauge, getShadowWidth, 0}},
+ {1604, {wxGauge, getValue, 0}},
+ {1605, {wxGauge, isVertical, 0}},
+ {1606, {wxGauge, setBezelFace, 1}},
+ {1607, {wxGauge, setRange, 1}},
+ {1608, {wxGauge, setShadowWidth, 1}},
+ {1609, {wxGauge, setValue, 1}},
+ {1610, {wxGauge, pulse, 0}},
+ {1611, {wxGauge, 'Destroy', undefined}},
+ {1612, {wxGenericDirCtrl, new_0, 0}},
+ {1613, {wxGenericDirCtrl, new_2, 2}},
+ {1614, {wxGenericDirCtrl, destruct, 0}},
+ {1615, {wxGenericDirCtrl, create, 2}},
+ {1616, {wxGenericDirCtrl, init, 0}},
+ {1617, {wxGenericDirCtrl, collapseTree, 0}},
+ {1618, {wxGenericDirCtrl, expandPath, 1}},
+ {1619, {wxGenericDirCtrl, getDefaultPath, 0}},
+ {1620, {wxGenericDirCtrl, getPath, 0}},
+ {1621, {wxGenericDirCtrl, getFilePath, 0}},
+ {1622, {wxGenericDirCtrl, getFilter, 0}},
+ {1623, {wxGenericDirCtrl, getFilterIndex, 0}},
+ {1624, {wxGenericDirCtrl, getRootId, 0}},
+ {1625, {wxGenericDirCtrl, getTreeCtrl, 0}},
+ {1626, {wxGenericDirCtrl, reCreateTree, 0}},
+ {1627, {wxGenericDirCtrl, setDefaultPath, 1}},
+ {1628, {wxGenericDirCtrl, setFilter, 1}},
+ {1629, {wxGenericDirCtrl, setFilterIndex, 1}},
+ {1630, {wxGenericDirCtrl, setPath, 1}},
+ {1632, {wxStaticBox, new_4, 4}},
+ {1633, {wxStaticBox, new_0, 0}},
+ {1634, {wxStaticBox, create, 4}},
+ {1635, {wxStaticBox, 'Destroy', undefined}},
+ {1637, {wxStaticLine, new_2, 2}},
+ {1638, {wxStaticLine, new_0, 0}},
+ {1639, {wxStaticLine, create, 2}},
+ {1640, {wxStaticLine, isVertical, 0}},
+ {1641, {wxStaticLine, getDefaultSize, 0}},
+ {1642, {wxStaticLine, 'Destroy', undefined}},
+ {1645, {wxListBox, new_3, 3}},
+ {1646, {wxListBox, new_0, 0}},
+ {1648, {wxListBox, destruct, 0}},
+ {1650, {wxListBox, create, 6}},
+ {1651, {wxListBox, deselect, 1}},
+ {1652, {wxListBox, getSelections, 1}},
+ {1653, {wxListBox, insertItems, 2}},
+ {1654, {wxListBox, isSelected, 1}},
+ {1655, {wxListBox, set, 1}},
+ {1656, {wxListBox, hitTest, 1}},
+ {1657, {wxListBox, setFirstItem_1_0, 1}},
+ {1658, {wxListBox, setFirstItem_1_1, 1}},
+ {1659, {wxListCtrl, new_0, 0}},
+ {1660, {wxListCtrl, new_2, 2}},
+ {1661, {wxListCtrl, arrange, 1}},
+ {1662, {wxListCtrl, assignImageList, 2}},
+ {1663, {wxListCtrl, clearAll, 0}},
+ {1664, {wxListCtrl, create, 2}},
+ {1665, {wxListCtrl, deleteAllItems, 0}},
+ {1666, {wxListCtrl, deleteColumn, 1}},
+ {1667, {wxListCtrl, deleteItem, 1}},
+ {1668, {wxListCtrl, editLabel, 1}},
+ {1669, {wxListCtrl, ensureVisible, 1}},
+ {1670, {wxListCtrl, findItem_3_0, 3}},
+ {1671, {wxListCtrl, findItem_3_1, 3}},
+ {1672, {wxListCtrl, getColumn, 2}},
+ {1673, {wxListCtrl, getColumnCount, 0}},
+ {1674, {wxListCtrl, getColumnWidth, 1}},
+ {1675, {wxListCtrl, getCountPerPage, 0}},
+ {1676, {wxListCtrl, getEditControl, 0}},
+ {1677, {wxListCtrl, getImageList, 1}},
+ {1678, {wxListCtrl, getItem, 1}},
+ {1679, {wxListCtrl, getItemBackgroundColour, 1}},
+ {1680, {wxListCtrl, getItemCount, 0}},
+ {1681, {wxListCtrl, getItemData, 1}},
+ {1682, {wxListCtrl, getItemFont, 1}},
+ {1683, {wxListCtrl, getItemPosition, 2}},
+ {1684, {wxListCtrl, getItemRect, 3}},
+ {1685, {wxListCtrl, getItemSpacing, 0}},
+ {1686, {wxListCtrl, getItemState, 2}},
+ {1687, {wxListCtrl, getItemText, 1}},
+ {1688, {wxListCtrl, getItemTextColour, 1}},
+ {1689, {wxListCtrl, getNextItem, 2}},
+ {1690, {wxListCtrl, getSelectedItemCount, 0}},
+ {1691, {wxListCtrl, getTextColour, 0}},
+ {1692, {wxListCtrl, getTopItem, 0}},
+ {1693, {wxListCtrl, getViewRect, 0}},
+ {1694, {wxListCtrl, hitTest, 2}},
+ {1695, {wxListCtrl, insertColumn_2, 2}},
+ {1696, {wxListCtrl, insertColumn_3, 3}},
+ {1697, {wxListCtrl, insertItem_1, 1}},
+ {1698, {wxListCtrl, insertItem_2_1, 2}},
+ {1699, {wxListCtrl, insertItem_2_0, 2}},
+ {1700, {wxListCtrl, insertItem_3, 3}},
+ {1701, {wxListCtrl, refreshItem, 1}},
+ {1702, {wxListCtrl, refreshItems, 2}},
+ {1703, {wxListCtrl, scrollList, 2}},
+ {1704, {wxListCtrl, setBackgroundColour, 1}},
+ {1705, {wxListCtrl, setColumn, 2}},
+ {1706, {wxListCtrl, setColumnWidth, 2}},
+ {1707, {wxListCtrl, setImageList, 2}},
+ {1708, {wxListCtrl, setItem_1, 1}},
+ {1709, {wxListCtrl, setItem_4, 4}},
+ {1710, {wxListCtrl, setItemBackgroundColour, 2}},
+ {1711, {wxListCtrl, setItemCount, 1}},
+ {1712, {wxListCtrl, setItemData, 2}},
+ {1713, {wxListCtrl, setItemFont, 2}},
+ {1714, {wxListCtrl, setItemImage, 3}},
+ {1715, {wxListCtrl, setItemColumnImage, 3}},
+ {1716, {wxListCtrl, setItemPosition, 2}},
+ {1717, {wxListCtrl, setItemState, 3}},
+ {1718, {wxListCtrl, setItemText, 2}},
+ {1719, {wxListCtrl, setItemTextColour, 2}},
+ {1720, {wxListCtrl, setSingleStyle, 2}},
+ {1721, {wxListCtrl, setTextColour, 1}},
+ {1722, {wxListCtrl, setWindowStyleFlag, 1}},
+ {1723, {wxListCtrl, sortItems, 2}},
+ {1724, {wxListCtrl, 'Destroy', undefined}},
+ {1725, {wxListView, clearColumnImage, 1}},
+ {1726, {wxListView, focus, 1}},
+ {1727, {wxListView, getFirstSelected, 0}},
+ {1728, {wxListView, getFocusedItem, 0}},
+ {1729, {wxListView, getNextSelected, 1}},
+ {1730, {wxListView, isSelected, 1}},
+ {1731, {wxListView, select, 2}},
+ {1732, {wxListView, setColumnImage, 2}},
+ {1733, {wxListItem, new_0, 0}},
+ {1734, {wxListItem, new_1, 1}},
+ {1735, {wxListItem, destruct, 0}},
+ {1736, {wxListItem, clear, 0}},
+ {1737, {wxListItem, getAlign, 0}},
+ {1738, {wxListItem, getBackgroundColour, 0}},
+ {1739, {wxListItem, getColumn, 0}},
+ {1740, {wxListItem, getFont, 0}},
+ {1741, {wxListItem, getId, 0}},
+ {1742, {wxListItem, getImage, 0}},
+ {1743, {wxListItem, getMask, 0}},
+ {1744, {wxListItem, getState, 0}},
+ {1745, {wxListItem, getText, 0}},
+ {1746, {wxListItem, getTextColour, 0}},
+ {1747, {wxListItem, getWidth, 0}},
+ {1748, {wxListItem, setAlign, 1}},
+ {1749, {wxListItem, setBackgroundColour, 1}},
+ {1750, {wxListItem, setColumn, 1}},
+ {1751, {wxListItem, setFont, 1}},
+ {1752, {wxListItem, setId, 1}},
+ {1753, {wxListItem, setImage, 1}},
+ {1754, {wxListItem, setMask, 1}},
+ {1755, {wxListItem, setState, 1}},
+ {1756, {wxListItem, setStateMask, 1}},
+ {1757, {wxListItem, setText, 1}},
+ {1758, {wxListItem, setTextColour, 1}},
+ {1759, {wxListItem, setWidth, 1}},
+ {1760, {wxListItemAttr, new_0, 0}},
+ {1761, {wxListItemAttr, new_3, 3}},
+ {1762, {wxListItemAttr, getBackgroundColour, 0}},
+ {1763, {wxListItemAttr, getFont, 0}},
+ {1764, {wxListItemAttr, getTextColour, 0}},
+ {1765, {wxListItemAttr, hasBackgroundColour, 0}},
+ {1766, {wxListItemAttr, hasFont, 0}},
+ {1767, {wxListItemAttr, hasTextColour, 0}},
+ {1768, {wxListItemAttr, setBackgroundColour, 1}},
+ {1769, {wxListItemAttr, setFont, 1}},
+ {1770, {wxListItemAttr, setTextColour, 1}},
+ {1771, {wxListItemAttr, 'Destroy', undefined}},
+ {1772, {wxImageList, new_0, 0}},
+ {1773, {wxImageList, new_3, 3}},
+ {1774, {wxImageList, add_1, 1}},
+ {1775, {wxImageList, add_2_0, 2}},
+ {1776, {wxImageList, add_2_1, 2}},
+ {1777, {wxImageList, create, 3}},
+ {1779, {wxImageList, draw, 5}},
+ {1780, {wxImageList, getBitmap, 1}},
+ {1781, {wxImageList, getIcon, 1}},
+ {1782, {wxImageList, getImageCount, 0}},
+ {1783, {wxImageList, getSize, 3}},
+ {1784, {wxImageList, remove, 1}},
+ {1785, {wxImageList, removeAll, 0}},
+ {1786, {wxImageList, replace_2, 2}},
+ {1787, {wxImageList, replace_3, 3}},
+ {1788, {wxImageList, 'Destroy', undefined}},
+ {1789, {wxTextAttr, new_0, 0}},
+ {1790, {wxTextAttr, new_2, 2}},
+ {1791, {wxTextAttr, getAlignment, 0}},
+ {1792, {wxTextAttr, getBackgroundColour, 0}},
+ {1793, {wxTextAttr, getFont, 0}},
+ {1794, {wxTextAttr, getLeftIndent, 0}},
+ {1795, {wxTextAttr, getLeftSubIndent, 0}},
+ {1796, {wxTextAttr, getRightIndent, 0}},
+ {1797, {wxTextAttr, getTabs, 0}},
+ {1798, {wxTextAttr, getTextColour, 0}},
+ {1799, {wxTextAttr, hasBackgroundColour, 0}},
+ {1800, {wxTextAttr, hasFont, 0}},
+ {1801, {wxTextAttr, hasTextColour, 0}},
+ {1802, {wxTextAttr, getFlags, 0}},
+ {1803, {wxTextAttr, isDefault, 0}},
+ {1804, {wxTextAttr, setAlignment, 1}},
+ {1805, {wxTextAttr, setBackgroundColour, 1}},
+ {1806, {wxTextAttr, setFlags, 1}},
+ {1807, {wxTextAttr, setFont, 2}},
+ {1808, {wxTextAttr, setLeftIndent, 2}},
+ {1809, {wxTextAttr, setRightIndent, 1}},
+ {1810, {wxTextAttr, setTabs, 1}},
+ {1811, {wxTextAttr, setTextColour, 1}},
+ {1812, {wxTextAttr, 'Destroy', undefined}},
+ {1814, {wxTextCtrl, new_3, 3}},
+ {1815, {wxTextCtrl, new_0, 0}},
+ {1817, {wxTextCtrl, destruct, 0}},
+ {1818, {wxTextCtrl, appendText, 1}},
+ {1819, {wxTextCtrl, canCopy, 0}},
+ {1820, {wxTextCtrl, canCut, 0}},
+ {1821, {wxTextCtrl, canPaste, 0}},
+ {1822, {wxTextCtrl, canRedo, 0}},
+ {1823, {wxTextCtrl, canUndo, 0}},
+ {1824, {wxTextCtrl, clear, 0}},
+ {1825, {wxTextCtrl, copy, 0}},
+ {1826, {wxTextCtrl, create, 3}},
+ {1827, {wxTextCtrl, cut, 0}},
+ {1828, {wxTextCtrl, discardEdits, 0}},
+ {1829, {wxTextCtrl, changeValue, 1}},
+ {1830, {wxTextCtrl, emulateKeyPress, 1}},
+ {1831, {wxTextCtrl, getDefaultStyle, 0}},
+ {1832, {wxTextCtrl, getInsertionPoint, 0}},
+ {1833, {wxTextCtrl, getLastPosition, 0}},
+ {1834, {wxTextCtrl, getLineLength, 1}},
+ {1835, {wxTextCtrl, getLineText, 1}},
+ {1836, {wxTextCtrl, getNumberOfLines, 0}},
+ {1837, {wxTextCtrl, getRange, 2}},
+ {1838, {wxTextCtrl, getSelection, 2}},
+ {1839, {wxTextCtrl, getStringSelection, 0}},
+ {1840, {wxTextCtrl, getStyle, 2}},
+ {1841, {wxTextCtrl, getValue, 0}},
+ {1842, {wxTextCtrl, isEditable, 0}},
+ {1843, {wxTextCtrl, isModified, 0}},
+ {1844, {wxTextCtrl, isMultiLine, 0}},
+ {1845, {wxTextCtrl, isSingleLine, 0}},
+ {1846, {wxTextCtrl, loadFile, 2}},
+ {1847, {wxTextCtrl, markDirty, 0}},
+ {1848, {wxTextCtrl, paste, 0}},
+ {1849, {wxTextCtrl, positionToXY, 3}},
+ {1850, {wxTextCtrl, redo, 0}},
+ {1851, {wxTextCtrl, remove, 2}},
+ {1852, {wxTextCtrl, replace, 3}},
+ {1853, {wxTextCtrl, saveFile, 1}},
+ {1854, {wxTextCtrl, setDefaultStyle, 1}},
+ {1855, {wxTextCtrl, setEditable, 1}},
+ {1856, {wxTextCtrl, setInsertionPoint, 1}},
+ {1857, {wxTextCtrl, setInsertionPointEnd, 0}},
+ {1859, {wxTextCtrl, setMaxLength, 1}},
+ {1860, {wxTextCtrl, setSelection, 2}},
+ {1861, {wxTextCtrl, setStyle, 3}},
+ {1862, {wxTextCtrl, setValue, 1}},
+ {1863, {wxTextCtrl, showPosition, 1}},
+ {1864, {wxTextCtrl, undo, 0}},
+ {1865, {wxTextCtrl, writeText, 1}},
+ {1866, {wxTextCtrl, xYToPosition, 2}},
+ {1869, {wxNotebook, new_0, 0}},
+ {1870, {wxNotebook, new_3, 3}},
+ {1871, {wxNotebook, destruct, 0}},
+ {1872, {wxNotebook, addPage, 3}},
+ {1873, {wxNotebook, advanceSelection, 1}},
+ {1874, {wxNotebook, assignImageList, 1}},
+ {1875, {wxNotebook, create, 3}},
+ {1876, {wxNotebook, deleteAllPages, 0}},
+ {1877, {wxNotebook, deletePage, 1}},
+ {1878, {wxNotebook, removePage, 1}},
+ {1879, {wxNotebook, getCurrentPage, 0}},
+ {1880, {wxNotebook, getImageList, 0}},
+ {1882, {wxNotebook, getPage, 1}},
+ {1883, {wxNotebook, getPageCount, 0}},
+ {1884, {wxNotebook, getPageImage, 1}},
+ {1885, {wxNotebook, getPageText, 1}},
+ {1886, {wxNotebook, getRowCount, 0}},
+ {1887, {wxNotebook, getSelection, 0}},
+ {1888, {wxNotebook, getThemeBackgroundColour, 0}},
+ {1890, {wxNotebook, hitTest, 2}},
+ {1892, {wxNotebook, insertPage, 4}},
+ {1893, {wxNotebook, setImageList, 1}},
+ {1894, {wxNotebook, setPadding, 1}},
+ {1895, {wxNotebook, setPageSize, 1}},
+ {1896, {wxNotebook, setPageImage, 2}},
+ {1897, {wxNotebook, setPageText, 2}},
+ {1898, {wxNotebook, setSelection, 1}},
+ {1899, {wxNotebook, changeSelection, 1}},
+ {1900, {wxChoicebook, new_0, 0}},
+ {1901, {wxChoicebook, new_3, 3}},
+ {1902, {wxChoicebook, addPage, 3}},
+ {1903, {wxChoicebook, advanceSelection, 1}},
+ {1904, {wxChoicebook, assignImageList, 1}},
+ {1905, {wxChoicebook, create, 3}},
+ {1906, {wxChoicebook, deleteAllPages, 0}},
+ {1907, {wxChoicebook, deletePage, 1}},
+ {1908, {wxChoicebook, removePage, 1}},
+ {1909, {wxChoicebook, getCurrentPage, 0}},
+ {1910, {wxChoicebook, getImageList, 0}},
+ {1912, {wxChoicebook, getPage, 1}},
+ {1913, {wxChoicebook, getPageCount, 0}},
+ {1914, {wxChoicebook, getPageImage, 1}},
+ {1915, {wxChoicebook, getPageText, 1}},
+ {1916, {wxChoicebook, getSelection, 0}},
+ {1917, {wxChoicebook, hitTest, 2}},
+ {1918, {wxChoicebook, insertPage, 4}},
+ {1919, {wxChoicebook, setImageList, 1}},
+ {1920, {wxChoicebook, setPageSize, 1}},
+ {1921, {wxChoicebook, setPageImage, 2}},
+ {1922, {wxChoicebook, setPageText, 2}},
+ {1923, {wxChoicebook, setSelection, 1}},
+ {1924, {wxChoicebook, changeSelection, 1}},
+ {1925, {wxChoicebook, 'Destroy', undefined}},
+ {1926, {wxToolbook, new_0, 0}},
+ {1927, {wxToolbook, new_3, 3}},
+ {1928, {wxToolbook, addPage, 3}},
+ {1929, {wxToolbook, advanceSelection, 1}},
+ {1930, {wxToolbook, assignImageList, 1}},
+ {1931, {wxToolbook, create, 3}},
+ {1932, {wxToolbook, deleteAllPages, 0}},
+ {1933, {wxToolbook, deletePage, 1}},
+ {1934, {wxToolbook, removePage, 1}},
+ {1935, {wxToolbook, getCurrentPage, 0}},
+ {1936, {wxToolbook, getImageList, 0}},
+ {1938, {wxToolbook, getPage, 1}},
+ {1939, {wxToolbook, getPageCount, 0}},
+ {1940, {wxToolbook, getPageImage, 1}},
+ {1941, {wxToolbook, getPageText, 1}},
+ {1942, {wxToolbook, getSelection, 0}},
+ {1944, {wxToolbook, hitTest, 2}},
+ {1945, {wxToolbook, insertPage, 4}},
+ {1946, {wxToolbook, setImageList, 1}},
+ {1947, {wxToolbook, setPageSize, 1}},
+ {1948, {wxToolbook, setPageImage, 2}},
+ {1949, {wxToolbook, setPageText, 2}},
+ {1950, {wxToolbook, setSelection, 1}},
+ {1951, {wxToolbook, changeSelection, 1}},
+ {1952, {wxToolbook, 'Destroy', undefined}},
+ {1953, {wxListbook, new_0, 0}},
+ {1954, {wxListbook, new_3, 3}},
+ {1955, {wxListbook, addPage, 3}},
+ {1956, {wxListbook, advanceSelection, 1}},
+ {1957, {wxListbook, assignImageList, 1}},
+ {1958, {wxListbook, create, 3}},
+ {1959, {wxListbook, deleteAllPages, 0}},
+ {1960, {wxListbook, deletePage, 1}},
+ {1961, {wxListbook, removePage, 1}},
+ {1962, {wxListbook, getCurrentPage, 0}},
+ {1963, {wxListbook, getImageList, 0}},
+ {1965, {wxListbook, getPage, 1}},
+ {1966, {wxListbook, getPageCount, 0}},
+ {1967, {wxListbook, getPageImage, 1}},
+ {1968, {wxListbook, getPageText, 1}},
+ {1969, {wxListbook, getSelection, 0}},
+ {1971, {wxListbook, hitTest, 2}},
+ {1972, {wxListbook, insertPage, 4}},
+ {1973, {wxListbook, setImageList, 1}},
+ {1974, {wxListbook, setPageSize, 1}},
+ {1975, {wxListbook, setPageImage, 2}},
+ {1976, {wxListbook, setPageText, 2}},
+ {1977, {wxListbook, setSelection, 1}},
+ {1978, {wxListbook, changeSelection, 1}},
+ {1979, {wxListbook, 'Destroy', undefined}},
+ {1980, {wxTreebook, new_0, 0}},
+ {1981, {wxTreebook, new_3, 3}},
+ {1982, {wxTreebook, addPage, 3}},
+ {1983, {wxTreebook, advanceSelection, 1}},
+ {1984, {wxTreebook, assignImageList, 1}},
+ {1985, {wxTreebook, create, 3}},
+ {1986, {wxTreebook, deleteAllPages, 0}},
+ {1987, {wxTreebook, deletePage, 1}},
+ {1988, {wxTreebook, removePage, 1}},
+ {1989, {wxTreebook, getCurrentPage, 0}},
+ {1990, {wxTreebook, getImageList, 0}},
+ {1992, {wxTreebook, getPage, 1}},
+ {1993, {wxTreebook, getPageCount, 0}},
+ {1994, {wxTreebook, getPageImage, 1}},
+ {1995, {wxTreebook, getPageText, 1}},
+ {1996, {wxTreebook, getSelection, 0}},
+ {1997, {wxTreebook, expandNode, 2}},
+ {1998, {wxTreebook, isNodeExpanded, 1}},
+ {2000, {wxTreebook, hitTest, 2}},
+ {2001, {wxTreebook, insertPage, 4}},
+ {2002, {wxTreebook, insertSubPage, 4}},
+ {2003, {wxTreebook, setImageList, 1}},
+ {2004, {wxTreebook, setPageSize, 1}},
+ {2005, {wxTreebook, setPageImage, 2}},
+ {2006, {wxTreebook, setPageText, 2}},
+ {2007, {wxTreebook, setSelection, 1}},
+ {2008, {wxTreebook, changeSelection, 1}},
+ {2009, {wxTreebook, 'Destroy', undefined}},
+ {2012, {wxTreeCtrl, new_2, 2}},
+ {2013, {wxTreeCtrl, new_0, 0}},
+ {2015, {wxTreeCtrl, destruct, 0}},
+ {2016, {wxTreeCtrl, addRoot, 2}},
+ {2017, {wxTreeCtrl, appendItem, 3}},
+ {2018, {wxTreeCtrl, assignImageList, 1}},
+ {2019, {wxTreeCtrl, assignStateImageList, 1}},
+ {2020, {wxTreeCtrl, collapse, 1}},
+ {2021, {wxTreeCtrl, collapseAndReset, 1}},
+ {2022, {wxTreeCtrl, create, 2}},
+ {2023, {wxTreeCtrl, delete, 1}},
+ {2024, {wxTreeCtrl, deleteAllItems, 0}},
+ {2025, {wxTreeCtrl, deleteChildren, 1}},
+ {2026, {wxTreeCtrl, editLabel, 1}},
+ {2027, {wxTreeCtrl, ensureVisible, 1}},
+ {2028, {wxTreeCtrl, expand, 1}},
+ {2029, {wxTreeCtrl, getBoundingRect, 3}},
+ {2031, {wxTreeCtrl, getChildrenCount, 2}},
+ {2032, {wxTreeCtrl, getCount, 0}},
+ {2033, {wxTreeCtrl, getEditControl, 0}},
+ {2034, {wxTreeCtrl, getFirstChild, 2}},
+ {2035, {wxTreeCtrl, getNextChild, 2}},
+ {2036, {wxTreeCtrl, getFirstVisibleItem, 0}},
+ {2037, {wxTreeCtrl, getImageList, 0}},
+ {2038, {wxTreeCtrl, getIndent, 0}},
+ {2039, {wxTreeCtrl, getItemBackgroundColour, 1}},
+ {2040, {wxTreeCtrl, getItemData, 1}},
+ {2041, {wxTreeCtrl, getItemFont, 1}},
+ {2042, {wxTreeCtrl, getItemImage_1, 1}},
+ {2043, {wxTreeCtrl, getItemImage_2, 2}},
+ {2044, {wxTreeCtrl, getItemText, 1}},
+ {2045, {wxTreeCtrl, getItemTextColour, 1}},
+ {2046, {wxTreeCtrl, getLastChild, 1}},
+ {2047, {wxTreeCtrl, getNextSibling, 1}},
+ {2048, {wxTreeCtrl, getNextVisible, 1}},
+ {2049, {wxTreeCtrl, getItemParent, 1}},
+ {2050, {wxTreeCtrl, getPrevSibling, 1}},
+ {2051, {wxTreeCtrl, getPrevVisible, 1}},
+ {2052, {wxTreeCtrl, getRootItem, 0}},
+ {2053, {wxTreeCtrl, getSelection, 0}},
+ {2054, {wxTreeCtrl, getSelections, 1}},
+ {2055, {wxTreeCtrl, getStateImageList, 0}},
+ {2056, {wxTreeCtrl, hitTest, 2}},
+ {2058, {wxTreeCtrl, insertItem, 4}},
+ {2059, {wxTreeCtrl, isBold, 1}},
+ {2060, {wxTreeCtrl, isExpanded, 1}},
+ {2061, {wxTreeCtrl, isSelected, 1}},
+ {2062, {wxTreeCtrl, isVisible, 1}},
+ {2063, {wxTreeCtrl, itemHasChildren, 1}},
+ {2064, {wxTreeCtrl, isTreeItemIdOk, 1}},
+ {2065, {wxTreeCtrl, prependItem, 3}},
+ {2066, {wxTreeCtrl, scrollTo, 1}},
+ {2067, {wxTreeCtrl, selectItem_1, 1}},
+ {2068, {wxTreeCtrl, selectItem_2, 2}},
+ {2069, {wxTreeCtrl, setIndent, 1}},
+ {2070, {wxTreeCtrl, setImageList, 1}},
+ {2071, {wxTreeCtrl, setItemBackgroundColour, 2}},
+ {2072, {wxTreeCtrl, setItemBold, 2}},
+ {2073, {wxTreeCtrl, setItemData, 2}},
+ {2074, {wxTreeCtrl, setItemDropHighlight, 2}},
+ {2075, {wxTreeCtrl, setItemFont, 2}},
+ {2076, {wxTreeCtrl, setItemHasChildren, 2}},
+ {2077, {wxTreeCtrl, setItemImage_2, 2}},
+ {2078, {wxTreeCtrl, setItemImage_3, 3}},
+ {2079, {wxTreeCtrl, setItemText, 2}},
+ {2080, {wxTreeCtrl, setItemTextColour, 2}},
+ {2081, {wxTreeCtrl, setStateImageList, 1}},
+ {2082, {wxTreeCtrl, setWindowStyle, 1}},
+ {2083, {wxTreeCtrl, sortChildren, 1}},
+ {2084, {wxTreeCtrl, toggle, 1}},
+ {2085, {wxTreeCtrl, toggleItemSelection, 1}},
+ {2086, {wxTreeCtrl, unselect, 0}},
+ {2087, {wxTreeCtrl, unselectAll, 0}},
+ {2088, {wxTreeCtrl, unselectItem, 1}},
+ {2089, {wxScrollBar, new_0, 0}},
+ {2090, {wxScrollBar, new_3, 3}},
+ {2091, {wxScrollBar, destruct, 0}},
+ {2092, {wxScrollBar, create, 3}},
+ {2093, {wxScrollBar, getRange, 0}},
+ {2094, {wxScrollBar, getPageSize, 0}},
+ {2095, {wxScrollBar, getThumbPosition, 0}},
+ {2096, {wxScrollBar, getThumbSize, 0}},
+ {2097, {wxScrollBar, setThumbPosition, 1}},
+ {2098, {wxScrollBar, setScrollbar, 5}},
+ {2100, {wxSpinButton, new_2, 2}},
+ {2101, {wxSpinButton, new_0, 0}},
+ {2102, {wxSpinButton, create, 2}},
+ {2103, {wxSpinButton, getMax, 0}},
+ {2104, {wxSpinButton, getMin, 0}},
+ {2105, {wxSpinButton, getValue, 0}},
+ {2106, {wxSpinButton, setRange, 2}},
+ {2107, {wxSpinButton, setValue, 1}},
+ {2108, {wxSpinButton, 'Destroy', undefined}},
+ {2109, {wxSpinCtrl, new_0, 0}},
+ {2110, {wxSpinCtrl, new_2, 2}},
+ {2112, {wxSpinCtrl, create, 2}},
+ {2115, {wxSpinCtrl, setValue_1_1, 1}},
+ {2116, {wxSpinCtrl, setValue_1_0, 1}},
+ {2118, {wxSpinCtrl, getValue, 0}},
+ {2120, {wxSpinCtrl, setRange, 2}},
+ {2121, {wxSpinCtrl, setSelection, 2}},
+ {2123, {wxSpinCtrl, getMin, 0}},
+ {2125, {wxSpinCtrl, getMax, 0}},
+ {2126, {wxSpinCtrl, 'Destroy', undefined}},
+ {2127, {wxStaticText, new_0, 0}},
+ {2128, {wxStaticText, new_4, 4}},
+ {2129, {wxStaticText, create, 4}},
+ {2130, {wxStaticText, getLabel, 0}},
+ {2131, {wxStaticText, setLabel, 1}},
+ {2132, {wxStaticText, wrap, 1}},
+ {2133, {wxStaticText, 'Destroy', undefined}},
+ {2134, {wxStaticBitmap, new_0, 0}},
+ {2135, {wxStaticBitmap, new_4, 4}},
+ {2136, {wxStaticBitmap, create, 4}},
+ {2137, {wxStaticBitmap, getBitmap, 0}},
+ {2138, {wxStaticBitmap, setBitmap, 1}},
+ {2139, {wxStaticBitmap, 'Destroy', undefined}},
+ {2140, {wxRadioBox, new, 7}},
+ {2142, {wxRadioBox, destruct, 0}},
+ {2143, {wxRadioBox, create, 7}},
+ {2144, {wxRadioBox, enable_2, 2}},
+ {2145, {wxRadioBox, enable_1, 1}},
+ {2146, {wxRadioBox, getSelection, 0}},
+ {2147, {wxRadioBox, getString, 1}},
+ {2148, {wxRadioBox, setSelection, 1}},
+ {2149, {wxRadioBox, show_2, 2}},
+ {2150, {wxRadioBox, show_1, 1}},
+ {2151, {wxRadioBox, getColumnCount, 0}},
+ {2152, {wxRadioBox, getItemHelpText, 1}},
+ {2153, {wxRadioBox, getItemToolTip, 1}},
+ {2155, {wxRadioBox, getItemFromPoint, 1}},
+ {2156, {wxRadioBox, getRowCount, 0}},
+ {2157, {wxRadioBox, isItemEnabled, 1}},
+ {2158, {wxRadioBox, isItemShown, 1}},
+ {2159, {wxRadioBox, setItemHelpText, 2}},
+ {2160, {wxRadioBox, setItemToolTip, 2}},
+ {2161, {wxRadioButton, new_0, 0}},
+ {2162, {wxRadioButton, new_4, 4}},
+ {2163, {wxRadioButton, create, 4}},
+ {2164, {wxRadioButton, getValue, 0}},
+ {2165, {wxRadioButton, setValue, 1}},
+ {2166, {wxRadioButton, 'Destroy', undefined}},
+ {2168, {wxSlider, new_6, 6}},
+ {2169, {wxSlider, new_0, 0}},
+ {2170, {wxSlider, create, 6}},
+ {2171, {wxSlider, getLineSize, 0}},
+ {2172, {wxSlider, getMax, 0}},
+ {2173, {wxSlider, getMin, 0}},
+ {2174, {wxSlider, getPageSize, 0}},
+ {2175, {wxSlider, getThumbLength, 0}},
+ {2176, {wxSlider, getValue, 0}},
+ {2177, {wxSlider, setLineSize, 1}},
+ {2178, {wxSlider, setPageSize, 1}},
+ {2179, {wxSlider, setRange, 2}},
+ {2180, {wxSlider, setThumbLength, 1}},
+ {2181, {wxSlider, setValue, 1}},
+ {2182, {wxSlider, 'Destroy', undefined}},
+ {2184, {wxDialog, new_4, 4}},
+ {2185, {wxDialog, new_0, 0}},
+ {2187, {wxDialog, destruct, 0}},
+ {2188, {wxDialog, create, 4}},
+ {2189, {wxDialog, createButtonSizer, 1}},
+ {2190, {wxDialog, createStdDialogButtonSizer, 1}},
+ {2191, {wxDialog, endModal, 1}},
+ {2192, {wxDialog, getAffirmativeId, 0}},
+ {2193, {wxDialog, getReturnCode, 0}},
+ {2194, {wxDialog, isModal, 0}},
+ {2195, {wxDialog, setAffirmativeId, 1}},
+ {2196, {wxDialog, setReturnCode, 1}},
+ {2197, {wxDialog, show, 1}},
+ {2198, {wxDialog, showModal, 0}},
+ {2199, {wxColourDialog, new_0, 0}},
+ {2200, {wxColourDialog, new_2, 2}},
+ {2201, {wxColourDialog, destruct, 0}},
+ {2202, {wxColourDialog, create, 2}},
+ {2203, {wxColourDialog, getColourData, 0}},
+ {2204, {wxColourData, new_0, 0}},
+ {2205, {wxColourData, new_1, 1}},
+ {2206, {wxColourData, destruct, 0}},
+ {2207, {wxColourData, getChooseFull, 0}},
+ {2208, {wxColourData, getColour, 0}},
+ {2210, {wxColourData, getCustomColour, 1}},
+ {2211, {wxColourData, setChooseFull, 1}},
+ {2212, {wxColourData, setColour, 1}},
+ {2213, {wxColourData, setCustomColour, 2}},
+ {2214, {wxPalette, new_0, 0}},
+ {2215, {wxPalette, new_4, 4}},
+ {2217, {wxPalette, destruct, 0}},
+ {2218, {wxPalette, create, 4}},
+ {2219, {wxPalette, getColoursCount, 0}},
+ {2220, {wxPalette, getPixel, 3}},
+ {2221, {wxPalette, getRGB, 4}},
+ {2222, {wxPalette, isOk, 0}},
+ {2226, {wxDirDialog, new, 2}},
+ {2227, {wxDirDialog, destruct, 0}},
+ {2228, {wxDirDialog, getPath, 0}},
+ {2229, {wxDirDialog, getMessage, 0}},
+ {2230, {wxDirDialog, setMessage, 1}},
+ {2231, {wxDirDialog, setPath, 1}},
+ {2235, {wxFileDialog, new, 2}},
+ {2236, {wxFileDialog, destruct, 0}},
+ {2237, {wxFileDialog, getDirectory, 0}},
+ {2238, {wxFileDialog, getFilename, 0}},
+ {2239, {wxFileDialog, getFilenames, 1}},
+ {2240, {wxFileDialog, getFilterIndex, 0}},
+ {2241, {wxFileDialog, getMessage, 0}},
+ {2242, {wxFileDialog, getPath, 0}},
+ {2243, {wxFileDialog, getPaths, 1}},
+ {2244, {wxFileDialog, getWildcard, 0}},
+ {2245, {wxFileDialog, setDirectory, 1}},
+ {2246, {wxFileDialog, setFilename, 1}},
+ {2247, {wxFileDialog, setFilterIndex, 1}},
+ {2248, {wxFileDialog, setMessage, 1}},
+ {2249, {wxFileDialog, setPath, 1}},
+ {2250, {wxFileDialog, setWildcard, 1}},
+ {2251, {wxPickerBase, setInternalMargin, 1}},
+ {2252, {wxPickerBase, getInternalMargin, 0}},
+ {2253, {wxPickerBase, setTextCtrlProportion, 1}},
+ {2254, {wxPickerBase, setPickerCtrlProportion, 1}},
+ {2255, {wxPickerBase, getTextCtrlProportion, 0}},
+ {2256, {wxPickerBase, getPickerCtrlProportion, 0}},
+ {2257, {wxPickerBase, hasTextCtrl, 0}},
+ {2258, {wxPickerBase, getTextCtrl, 0}},
+ {2259, {wxPickerBase, isTextCtrlGrowable, 0}},
+ {2260, {wxPickerBase, setPickerCtrlGrowable, 1}},
+ {2261, {wxPickerBase, setTextCtrlGrowable, 1}},
+ {2262, {wxPickerBase, isPickerCtrlGrowable, 0}},
+ {2263, {wxFilePickerCtrl, new_0, 0}},
+ {2264, {wxFilePickerCtrl, new_3, 3}},
+ {2265, {wxFilePickerCtrl, create, 3}},
+ {2266, {wxFilePickerCtrl, getPath, 0}},
+ {2267, {wxFilePickerCtrl, setPath, 1}},
+ {2268, {wxFilePickerCtrl, 'Destroy', undefined}},
+ {2269, {wxDirPickerCtrl, new_0, 0}},
+ {2270, {wxDirPickerCtrl, new_3, 3}},
+ {2271, {wxDirPickerCtrl, create, 3}},
+ {2272, {wxDirPickerCtrl, getPath, 0}},
+ {2273, {wxDirPickerCtrl, setPath, 1}},
+ {2274, {wxDirPickerCtrl, 'Destroy', undefined}},
+ {2275, {wxColourPickerCtrl, new_0, 0}},
+ {2276, {wxColourPickerCtrl, new_3, 3}},
+ {2277, {wxColourPickerCtrl, create, 3}},
+ {2278, {wxColourPickerCtrl, getColour, 0}},
+ {2279, {wxColourPickerCtrl, setColour_1_1, 1}},
+ {2280, {wxColourPickerCtrl, setColour_1_0, 1}},
+ {2281, {wxColourPickerCtrl, 'Destroy', undefined}},
+ {2282, {wxDatePickerCtrl, new_0, 0}},
+ {2283, {wxDatePickerCtrl, new_3, 3}},
+ {2284, {wxDatePickerCtrl, getRange, 2}},
+ {2285, {wxDatePickerCtrl, getValue, 0}},
+ {2286, {wxDatePickerCtrl, setRange, 2}},
+ {2287, {wxDatePickerCtrl, setValue, 1}},
+ {2288, {wxDatePickerCtrl, 'Destroy', undefined}},
+ {2289, {wxFontPickerCtrl, new_0, 0}},
+ {2290, {wxFontPickerCtrl, new_3, 3}},
+ {2291, {wxFontPickerCtrl, create, 3}},
+ {2292, {wxFontPickerCtrl, getSelectedFont, 0}},
+ {2293, {wxFontPickerCtrl, setSelectedFont, 1}},
+ {2294, {wxFontPickerCtrl, getMaxPointSize, 0}},
+ {2295, {wxFontPickerCtrl, setMaxPointSize, 1}},
+ {2296, {wxFontPickerCtrl, 'Destroy', undefined}},
+ {2299, {wxFindReplaceDialog, new_0, 0}},
+ {2300, {wxFindReplaceDialog, new_4, 4}},
+ {2301, {wxFindReplaceDialog, destruct, 0}},
+ {2302, {wxFindReplaceDialog, create, 4}},
+ {2303, {wxFindReplaceDialog, getData, 0}},
+ {2304, {wxFindReplaceData, new_0, 0}},
+ {2305, {wxFindReplaceData, new_1, 1}},
+ {2306, {wxFindReplaceData, getFindString, 0}},
+ {2307, {wxFindReplaceData, getReplaceString, 0}},
+ {2308, {wxFindReplaceData, getFlags, 0}},
+ {2309, {wxFindReplaceData, setFlags, 1}},
+ {2310, {wxFindReplaceData, setFindString, 1}},
+ {2311, {wxFindReplaceData, setReplaceString, 1}},
+ {2312, {wxFindReplaceData, 'Destroy', undefined}},
+ {2313, {wxMultiChoiceDialog, new_0, 0}},
+ {2315, {wxMultiChoiceDialog, new_5, 5}},
+ {2316, {wxMultiChoiceDialog, getSelections, 0}},
+ {2317, {wxMultiChoiceDialog, setSelections, 1}},
+ {2318, {wxMultiChoiceDialog, 'Destroy', undefined}},
+ {2319, {wxSingleChoiceDialog, new_0, 0}},
+ {2321, {wxSingleChoiceDialog, new_5, 5}},
+ {2322, {wxSingleChoiceDialog, getSelection, 0}},
+ {2323, {wxSingleChoiceDialog, getStringSelection, 0}},
+ {2324, {wxSingleChoiceDialog, setSelection, 1}},
+ {2325, {wxSingleChoiceDialog, 'Destroy', undefined}},
+ {2326, {wxTextEntryDialog, new, 3}},
+ {2327, {wxTextEntryDialog, getValue, 0}},
+ {2328, {wxTextEntryDialog, setValue, 1}},
+ {2329, {wxTextEntryDialog, 'Destroy', undefined}},
+ {2330, {wxPasswordEntryDialog, new, 3}},
+ {2331, {wxPasswordEntryDialog, 'Destroy', undefined}},
+ {2332, {wxFontData, new_0, 0}},
+ {2333, {wxFontData, new_1, 1}},
+ {2334, {wxFontData, destruct, 0}},
+ {2335, {wxFontData, enableEffects, 1}},
+ {2336, {wxFontData, getAllowSymbols, 0}},
+ {2337, {wxFontData, getColour, 0}},
+ {2338, {wxFontData, getChosenFont, 0}},
+ {2339, {wxFontData, getEnableEffects, 0}},
+ {2340, {wxFontData, getInitialFont, 0}},
+ {2341, {wxFontData, getShowHelp, 0}},
+ {2342, {wxFontData, setAllowSymbols, 1}},
+ {2343, {wxFontData, setChosenFont, 1}},
+ {2344, {wxFontData, setColour, 1}},
+ {2345, {wxFontData, setInitialFont, 1}},
+ {2346, {wxFontData, setRange, 2}},
+ {2347, {wxFontData, setShowHelp, 1}},
+ {2351, {wxFontDialog, new_0, 0}},
+ {2353, {wxFontDialog, new_2, 2}},
+ {2355, {wxFontDialog, create, 2}},
+ {2356, {wxFontDialog, getFontData, 0}},
+ {2358, {wxFontDialog, 'Destroy', undefined}},
+ {2359, {wxProgressDialog, new, 3}},
+ {2360, {wxProgressDialog, destruct, 0}},
+ {2361, {wxProgressDialog, resume, 0}},
+ {2362, {wxProgressDialog, update_2, 2}},
+ {2363, {wxProgressDialog, update_0, 0}},
+ {2364, {wxMessageDialog, new, 3}},
+ {2365, {wxMessageDialog, destruct, 0}},
+ {2366, {wxPageSetupDialog, new, 2}},
+ {2367, {wxPageSetupDialog, destruct, 0}},
+ {2368, {wxPageSetupDialog, getPageSetupData, 0}},
+ {2369, {wxPageSetupDialog, showModal, 0}},
+ {2370, {wxPageSetupDialogData, new_0, 0}},
+ {2371, {wxPageSetupDialogData, new_1_0, 1}},
+ {2372, {wxPageSetupDialogData, new_1_1, 1}},
+ {2373, {wxPageSetupDialogData, destruct, 0}},
+ {2374, {wxPageSetupDialogData, enableHelp, 1}},
+ {2375, {wxPageSetupDialogData, enableMargins, 1}},
+ {2376, {wxPageSetupDialogData, enableOrientation, 1}},
+ {2377, {wxPageSetupDialogData, enablePaper, 1}},
+ {2378, {wxPageSetupDialogData, enablePrinter, 1}},
+ {2379, {wxPageSetupDialogData, getDefaultMinMargins, 0}},
+ {2380, {wxPageSetupDialogData, getEnableMargins, 0}},
+ {2381, {wxPageSetupDialogData, getEnableOrientation, 0}},
+ {2382, {wxPageSetupDialogData, getEnablePaper, 0}},
+ {2383, {wxPageSetupDialogData, getEnablePrinter, 0}},
+ {2384, {wxPageSetupDialogData, getEnableHelp, 0}},
+ {2385, {wxPageSetupDialogData, getDefaultInfo, 0}},
+ {2386, {wxPageSetupDialogData, getMarginTopLeft, 0}},
+ {2387, {wxPageSetupDialogData, getMarginBottomRight, 0}},
+ {2388, {wxPageSetupDialogData, getMinMarginTopLeft, 0}},
+ {2389, {wxPageSetupDialogData, getMinMarginBottomRight, 0}},
+ {2390, {wxPageSetupDialogData, getPaperId, 0}},
+ {2391, {wxPageSetupDialogData, getPaperSize, 0}},
+ {2393, {wxPageSetupDialogData, getPrintData, 0}},
+ {2394, {wxPageSetupDialogData, isOk, 0}},
+ {2395, {wxPageSetupDialogData, setDefaultInfo, 1}},
+ {2396, {wxPageSetupDialogData, setDefaultMinMargins, 1}},
+ {2397, {wxPageSetupDialogData, setMarginTopLeft, 1}},
+ {2398, {wxPageSetupDialogData, setMarginBottomRight, 1}},
+ {2399, {wxPageSetupDialogData, setMinMarginTopLeft, 1}},
+ {2400, {wxPageSetupDialogData, setMinMarginBottomRight, 1}},
+ {2401, {wxPageSetupDialogData, setPaperId, 1}},
+ {2402, {wxPageSetupDialogData, setPaperSize_1_1, 1}},
+ {2403, {wxPageSetupDialogData, setPaperSize_1_0, 1}},
+ {2404, {wxPageSetupDialogData, setPrintData, 1}},
+ {2405, {wxPrintDialog, new_2_0, 2}},
+ {2406, {wxPrintDialog, new_2_1, 2}},
+ {2407, {wxPrintDialog, destruct, 0}},
+ {2408, {wxPrintDialog, getPrintDialogData, 0}},
+ {2409, {wxPrintDialog, getPrintDC, 0}},
+ {2410, {wxPrintDialogData, new_0, 0}},
+ {2411, {wxPrintDialogData, new_1_1, 1}},
+ {2412, {wxPrintDialogData, new_1_0, 1}},
+ {2413, {wxPrintDialogData, destruct, 0}},
+ {2414, {wxPrintDialogData, enableHelp, 1}},
+ {2415, {wxPrintDialogData, enablePageNumbers, 1}},
+ {2416, {wxPrintDialogData, enablePrintToFile, 1}},
+ {2417, {wxPrintDialogData, enableSelection, 1}},
+ {2418, {wxPrintDialogData, getAllPages, 0}},
+ {2419, {wxPrintDialogData, getCollate, 0}},
+ {2420, {wxPrintDialogData, getFromPage, 0}},
+ {2421, {wxPrintDialogData, getMaxPage, 0}},
+ {2422, {wxPrintDialogData, getMinPage, 0}},
+ {2423, {wxPrintDialogData, getNoCopies, 0}},
+ {2424, {wxPrintDialogData, getPrintData, 0}},
+ {2425, {wxPrintDialogData, getPrintToFile, 0}},
+ {2426, {wxPrintDialogData, getSelection, 0}},
+ {2427, {wxPrintDialogData, getToPage, 0}},
+ {2428, {wxPrintDialogData, isOk, 0}},
+ {2429, {wxPrintDialogData, setCollate, 1}},
+ {2430, {wxPrintDialogData, setFromPage, 1}},
+ {2431, {wxPrintDialogData, setMaxPage, 1}},
+ {2432, {wxPrintDialogData, setMinPage, 1}},
+ {2433, {wxPrintDialogData, setNoCopies, 1}},
+ {2434, {wxPrintDialogData, setPrintData, 1}},
+ {2435, {wxPrintDialogData, setPrintToFile, 1}},
+ {2436, {wxPrintDialogData, setSelection, 1}},
+ {2437, {wxPrintDialogData, setToPage, 1}},
+ {2438, {wxPrintData, new_0, 0}},
+ {2439, {wxPrintData, new_1, 1}},
+ {2440, {wxPrintData, destruct, 0}},
+ {2441, {wxPrintData, getCollate, 0}},
+ {2442, {wxPrintData, getBin, 0}},
+ {2443, {wxPrintData, getColour, 0}},
+ {2444, {wxPrintData, getDuplex, 0}},
+ {2445, {wxPrintData, getNoCopies, 0}},
+ {2446, {wxPrintData, getOrientation, 0}},
+ {2447, {wxPrintData, getPaperId, 0}},
+ {2448, {wxPrintData, getPrinterName, 0}},
+ {2449, {wxPrintData, getQuality, 0}},
+ {2450, {wxPrintData, isOk, 0}},
+ {2451, {wxPrintData, setBin, 1}},
+ {2452, {wxPrintData, setCollate, 1}},
+ {2453, {wxPrintData, setColour, 1}},
+ {2454, {wxPrintData, setDuplex, 1}},
+ {2455, {wxPrintData, setNoCopies, 1}},
+ {2456, {wxPrintData, setOrientation, 1}},
+ {2457, {wxPrintData, setPaperId, 1}},
+ {2458, {wxPrintData, setPrinterName, 1}},
+ {2459, {wxPrintData, setQuality, 1}},
+ {2462, {wxPrintPreview, new_2, 2}},
+ {2463, {wxPrintPreview, new_3, 3}},
+ {2465, {wxPrintPreview, destruct, 0}},
+ {2466, {wxPrintPreview, getCanvas, 0}},
+ {2467, {wxPrintPreview, getCurrentPage, 0}},
+ {2468, {wxPrintPreview, getFrame, 0}},
+ {2469, {wxPrintPreview, getMaxPage, 0}},
+ {2470, {wxPrintPreview, getMinPage, 0}},
+ {2471, {wxPrintPreview, getPrintout, 0}},
+ {2472, {wxPrintPreview, getPrintoutForPrinting, 0}},
+ {2473, {wxPrintPreview, isOk, 0}},
+ {2474, {wxPrintPreview, paintPage, 2}},
+ {2475, {wxPrintPreview, print, 1}},
+ {2476, {wxPrintPreview, renderPage, 1}},
+ {2477, {wxPrintPreview, setCanvas, 1}},
+ {2478, {wxPrintPreview, setCurrentPage, 1}},
+ {2479, {wxPrintPreview, setFrame, 1}},
+ {2480, {wxPrintPreview, setPrintout, 1}},
+ {2481, {wxPrintPreview, setZoom, 1}},
+ {2482, {wxPreviewFrame, new, 3}},
+ {2483, {wxPreviewFrame, destruct, 0}},
+ {2484, {wxPreviewFrame, createControlBar, 0}},
+ {2485, {wxPreviewFrame, createCanvas, 0}},
+ {2486, {wxPreviewFrame, initialize, 0}},
+ {2487, {wxPreviewFrame, onCloseWindow, 1}},
+ {2488, {wxPreviewControlBar, new, 4}},
+ {2489, {wxPreviewControlBar, destruct, 0}},
+ {2490, {wxPreviewControlBar, createButtons, 0}},
+ {2491, {wxPreviewControlBar, getPrintPreview, 0}},
+ {2492, {wxPreviewControlBar, getZoomControl, 0}},
+ {2493, {wxPreviewControlBar, setZoomControl, 1}},
+ {2495, {wxPrinter, new, 1}},
+ {2496, {wxPrinter, createAbortWindow, 2}},
+ {2497, {wxPrinter, getAbort, 0}},
+ {2498, {wxPrinter, getLastError, 0}},
+ {2499, {wxPrinter, getPrintDialogData, 0}},
+ {2500, {wxPrinter, print, 3}},
+ {2501, {wxPrinter, printDialog, 1}},
+ {2502, {wxPrinter, reportError, 3}},
+ {2503, {wxPrinter, setup, 1}},
+ {2504, {wxPrinter, 'Destroy', undefined}},
+ {2505, {wxXmlResource, new_1, 1}},
+ {2506, {wxXmlResource, new_2, 2}},
+ {2507, {wxXmlResource, destruct, 0}},
+ {2508, {wxXmlResource, attachUnknownControl, 3}},
+ {2509, {wxXmlResource, clearHandlers, 0}},
+ {2510, {wxXmlResource, compareVersion, 4}},
+ {2511, {wxXmlResource, get, 0}},
+ {2512, {wxXmlResource, getFlags, 0}},
+ {2513, {wxXmlResource, getVersion, 0}},
+ {2514, {wxXmlResource, getXRCID, 2}},
+ {2515, {wxXmlResource, initAllHandlers, 0}},
+ {2516, {wxXmlResource, load, 1}},
+ {2517, {wxXmlResource, loadBitmap, 1}},
+ {2518, {wxXmlResource, loadDialog_2, 2}},
+ {2519, {wxXmlResource, loadDialog_3, 3}},
+ {2520, {wxXmlResource, loadFrame_2, 2}},
+ {2521, {wxXmlResource, loadFrame_3, 3}},
+ {2522, {wxXmlResource, loadIcon, 1}},
+ {2523, {wxXmlResource, loadMenu, 1}},
+ {2524, {wxXmlResource, loadMenuBar_2, 2}},
+ {2525, {wxXmlResource, loadMenuBar_1, 1}},
+ {2526, {wxXmlResource, loadPanel_2, 2}},
+ {2527, {wxXmlResource, loadPanel_3, 3}},
+ {2528, {wxXmlResource, loadToolBar, 2}},
+ {2529, {wxXmlResource, set, 1}},
+ {2530, {wxXmlResource, setFlags, 1}},
+ {2531, {wxXmlResource, unload, 1}},
+ {2532, {wxXmlResource, xrcctrl, 3}},
+ {2533, {wxHtmlEasyPrinting, new, 1}},
+ {2534, {wxHtmlEasyPrinting, destruct, 0}},
+ {2535, {wxHtmlEasyPrinting, getPrintData, 0}},
+ {2536, {wxHtmlEasyPrinting, getPageSetupData, 0}},
+ {2537, {wxHtmlEasyPrinting, previewFile, 1}},
+ {2538, {wxHtmlEasyPrinting, previewText, 2}},
+ {2539, {wxHtmlEasyPrinting, printFile, 1}},
+ {2540, {wxHtmlEasyPrinting, printText, 2}},
+ {2541, {wxHtmlEasyPrinting, pageSetup, 0}},
+ {2542, {wxHtmlEasyPrinting, setFonts, 3}},
+ {2543, {wxHtmlEasyPrinting, setHeader, 2}},
+ {2544, {wxHtmlEasyPrinting, setFooter, 2}},
+ {2546, {wxGLCanvas, new_2, 2}},
+ {2547, {wxGLCanvas, new_3_1, 3}},
+ {2548, {wxGLCanvas, new_3_0, 3}},
+ {2549, {wxGLCanvas, getContext, 0}},
+ {2551, {wxGLCanvas, setCurrent, 0}},
+ {2552, {wxGLCanvas, swapBuffers, 0}},
+ {2553, {wxGLCanvas, 'Destroy', undefined}},
+ {2554, {wxAuiManager, new, 1}},
+ {2555, {wxAuiManager, destruct, 0}},
+ {2556, {wxAuiManager, addPane_2_1, 2}},
+ {2557, {wxAuiManager, addPane_3, 3}},
+ {2558, {wxAuiManager, addPane_2_0, 2}},
+ {2559, {wxAuiManager, detachPane, 1}},
+ {2560, {wxAuiManager, getAllPanes, 0}},
+ {2561, {wxAuiManager, getArtProvider, 0}},
+ {2562, {wxAuiManager, getDockSizeConstraint, 2}},
+ {2563, {wxAuiManager, getFlags, 0}},
+ {2564, {wxAuiManager, getManagedWindow, 0}},
+ {2565, {wxAuiManager, getManager, 1}},
+ {2566, {wxAuiManager, getPane_1_1, 1}},
+ {2567, {wxAuiManager, getPane_1_0, 1}},
+ {2568, {wxAuiManager, hideHint, 0}},
+ {2569, {wxAuiManager, insertPane, 3}},
+ {2570, {wxAuiManager, loadPaneInfo, 2}},
+ {2571, {wxAuiManager, loadPerspective, 2}},
+ {2572, {wxAuiManager, savePaneInfo, 1}},
+ {2573, {wxAuiManager, savePerspective, 0}},
+ {2574, {wxAuiManager, setArtProvider, 1}},
+ {2575, {wxAuiManager, setDockSizeConstraint, 2}},
+ {2576, {wxAuiManager, setFlags, 1}},
+ {2577, {wxAuiManager, setManagedWindow, 1}},
+ {2578, {wxAuiManager, showHint, 1}},
+ {2579, {wxAuiManager, unInit, 0}},
+ {2580, {wxAuiManager, update, 0}},
+ {2581, {wxAuiPaneInfo, new_0, 0}},
+ {2582, {wxAuiPaneInfo, new_1, 1}},
+ {2583, {wxAuiPaneInfo, destruct, 0}},
+ {2584, {wxAuiPaneInfo, bestSize_1, 1}},
+ {2585, {wxAuiPaneInfo, bestSize_2, 2}},
+ {2586, {wxAuiPaneInfo, bottom, 0}},
+ {2587, {wxAuiPaneInfo, bottomDockable, 1}},
+ {2588, {wxAuiPaneInfo, caption, 1}},
+ {2589, {wxAuiPaneInfo, captionVisible, 1}},
+ {2590, {wxAuiPaneInfo, centre, 0}},
+ {2591, {wxAuiPaneInfo, centrePane, 0}},
+ {2592, {wxAuiPaneInfo, closeButton, 1}},
+ {2593, {wxAuiPaneInfo, defaultPane, 0}},
+ {2594, {wxAuiPaneInfo, destroyOnClose, 1}},
+ {2595, {wxAuiPaneInfo, direction, 1}},
+ {2596, {wxAuiPaneInfo, dock, 0}},
+ {2597, {wxAuiPaneInfo, dockable, 1}},
+ {2598, {wxAuiPaneInfo, fixed, 0}},
+ {2599, {wxAuiPaneInfo, float, 0}},
+ {2600, {wxAuiPaneInfo, floatable, 1}},
+ {2601, {wxAuiPaneInfo, floatingPosition_1, 1}},
+ {2602, {wxAuiPaneInfo, floatingPosition_2, 2}},
+ {2603, {wxAuiPaneInfo, floatingSize_1, 1}},
+ {2604, {wxAuiPaneInfo, floatingSize_2, 2}},
+ {2605, {wxAuiPaneInfo, gripper, 1}},
+ {2606, {wxAuiPaneInfo, gripperTop, 1}},
+ {2607, {wxAuiPaneInfo, hasBorder, 0}},
+ {2608, {wxAuiPaneInfo, hasCaption, 0}},
+ {2609, {wxAuiPaneInfo, hasCloseButton, 0}},
+ {2610, {wxAuiPaneInfo, hasFlag, 1}},
+ {2611, {wxAuiPaneInfo, hasGripper, 0}},
+ {2612, {wxAuiPaneInfo, hasGripperTop, 0}},
+ {2613, {wxAuiPaneInfo, hasMaximizeButton, 0}},
+ {2614, {wxAuiPaneInfo, hasMinimizeButton, 0}},
+ {2615, {wxAuiPaneInfo, hasPinButton, 0}},
+ {2616, {wxAuiPaneInfo, hide, 0}},
+ {2617, {wxAuiPaneInfo, isBottomDockable, 0}},
+ {2618, {wxAuiPaneInfo, isDocked, 0}},
+ {2619, {wxAuiPaneInfo, isFixed, 0}},
+ {2620, {wxAuiPaneInfo, isFloatable, 0}},
+ {2621, {wxAuiPaneInfo, isFloating, 0}},
+ {2622, {wxAuiPaneInfo, isLeftDockable, 0}},
+ {2623, {wxAuiPaneInfo, isMovable, 0}},
+ {2624, {wxAuiPaneInfo, isOk, 0}},
+ {2625, {wxAuiPaneInfo, isResizable, 0}},
+ {2626, {wxAuiPaneInfo, isRightDockable, 0}},
+ {2627, {wxAuiPaneInfo, isShown, 0}},
+ {2628, {wxAuiPaneInfo, isToolbar, 0}},
+ {2629, {wxAuiPaneInfo, isTopDockable, 0}},
+ {2630, {wxAuiPaneInfo, layer, 1}},
+ {2631, {wxAuiPaneInfo, left, 0}},
+ {2632, {wxAuiPaneInfo, leftDockable, 1}},
+ {2633, {wxAuiPaneInfo, maxSize_1, 1}},
+ {2634, {wxAuiPaneInfo, maxSize_2, 2}},
+ {2635, {wxAuiPaneInfo, maximizeButton, 1}},
+ {2636, {wxAuiPaneInfo, minSize_1, 1}},
+ {2637, {wxAuiPaneInfo, minSize_2, 2}},
+ {2638, {wxAuiPaneInfo, minimizeButton, 1}},
+ {2639, {wxAuiPaneInfo, movable, 1}},
+ {2640, {wxAuiPaneInfo, name, 1}},
+ {2641, {wxAuiPaneInfo, paneBorder, 1}},
+ {2642, {wxAuiPaneInfo, pinButton, 1}},
+ {2643, {wxAuiPaneInfo, position, 1}},
+ {2644, {wxAuiPaneInfo, resizable, 1}},
+ {2645, {wxAuiPaneInfo, right, 0}},
+ {2646, {wxAuiPaneInfo, rightDockable, 1}},
+ {2647, {wxAuiPaneInfo, row, 1}},
+ {2648, {wxAuiPaneInfo, safeSet, 1}},
+ {2649, {wxAuiPaneInfo, setFlag, 2}},
+ {2650, {wxAuiPaneInfo, show, 1}},
+ {2651, {wxAuiPaneInfo, toolbarPane, 0}},
+ {2652, {wxAuiPaneInfo, top, 0}},
+ {2653, {wxAuiPaneInfo, topDockable, 1}},
+ {2654, {wxAuiPaneInfo, window, 1}},
+ {2655, {wxAuiPaneInfo, getWindow, 0}},
+ {2656, {wxAuiPaneInfo, getFrame, 0}},
+ {2657, {wxAuiPaneInfo, getDirection, 0}},
+ {2658, {wxAuiPaneInfo, getLayer, 0}},
+ {2659, {wxAuiPaneInfo, getRow, 0}},
+ {2660, {wxAuiPaneInfo, getPosition, 0}},
+ {2661, {wxAuiPaneInfo, getFloatingPosition, 0}},
+ {2662, {wxAuiPaneInfo, getFloatingSize, 0}},
+ {2663, {wxAuiNotebook, new_0, 0}},
+ {2664, {wxAuiNotebook, new_2, 2}},
+ {2665, {wxAuiNotebook, addPage, 3}},
+ {2666, {wxAuiNotebook, create, 2}},
+ {2667, {wxAuiNotebook, deletePage, 1}},
+ {2668, {wxAuiNotebook, getArtProvider, 0}},
+ {2669, {wxAuiNotebook, getPage, 1}},
+ {2670, {wxAuiNotebook, getPageBitmap, 1}},
+ {2671, {wxAuiNotebook, getPageCount, 0}},
+ {2672, {wxAuiNotebook, getPageIndex, 1}},
+ {2673, {wxAuiNotebook, getPageText, 1}},
+ {2674, {wxAuiNotebook, getSelection, 0}},
+ {2675, {wxAuiNotebook, insertPage, 4}},
+ {2676, {wxAuiNotebook, removePage, 1}},
+ {2677, {wxAuiNotebook, setArtProvider, 1}},
+ {2678, {wxAuiNotebook, setFont, 1}},
+ {2679, {wxAuiNotebook, setPageBitmap, 2}},
+ {2680, {wxAuiNotebook, setPageText, 2}},
+ {2681, {wxAuiNotebook, setSelection, 1}},
+ {2682, {wxAuiNotebook, setTabCtrlHeight, 1}},
+ {2683, {wxAuiNotebook, setUniformBitmapSize, 1}},
+ {2684, {wxAuiNotebook, 'Destroy', undefined}},
+ {2685, {wxAuiTabArt, setFlags, 1}},
+ {2686, {wxAuiTabArt, setMeasuringFont, 1}},
+ {2687, {wxAuiTabArt, setNormalFont, 1}},
+ {2688, {wxAuiTabArt, setSelectedFont, 1}},
+ {2689, {wxAuiTabArt, setColour, 1}},
+ {2690, {wxAuiTabArt, setActiveColour, 1}},
+ {2691, {wxAuiDockArt, getColour, 1}},
+ {2692, {wxAuiDockArt, getFont, 1}},
+ {2693, {wxAuiDockArt, getMetric, 1}},
+ {2694, {wxAuiDockArt, setColour, 2}},
+ {2695, {wxAuiDockArt, setFont, 2}},
+ {2696, {wxAuiDockArt, setMetric, 2}},
+ {2697, {wxAuiSimpleTabArt, new, 0}},
+ {2698, {wxAuiSimpleTabArt, 'Destroy', undefined}},
+ {2699, {wxMDIParentFrame, new_0, 0}},
+ {2700, {wxMDIParentFrame, new_4, 4}},
+ {2701, {wxMDIParentFrame, destruct, 0}},
+ {2702, {wxMDIParentFrame, activateNext, 0}},
+ {2703, {wxMDIParentFrame, activatePrevious, 0}},
+ {2704, {wxMDIParentFrame, arrangeIcons, 0}},
+ {2705, {wxMDIParentFrame, cascade, 0}},
+ {2706, {wxMDIParentFrame, create, 4}},
+ {2707, {wxMDIParentFrame, getActiveChild, 0}},
+ {2708, {wxMDIParentFrame, getClientWindow, 0}},
+ {2709, {wxMDIParentFrame, tile, 1}},
+ {2710, {wxMDIChildFrame, new_0, 0}},
+ {2711, {wxMDIChildFrame, new_4, 4}},
+ {2712, {wxMDIChildFrame, destruct, 0}},
+ {2713, {wxMDIChildFrame, activate, 0}},
+ {2714, {wxMDIChildFrame, create, 4}},
+ {2715, {wxMDIChildFrame, maximize, 1}},
+ {2716, {wxMDIChildFrame, restore, 0}},
+ {2717, {wxMDIClientWindow, new_0, 0}},
+ {2718, {wxMDIClientWindow, new_2, 2}},
+ {2719, {wxMDIClientWindow, destruct, 0}},
+ {2720, {wxMDIClientWindow, createClient, 2}},
+ {2721, {wxLayoutAlgorithm, new, 0}},
+ {2722, {wxLayoutAlgorithm, layoutFrame, 2}},
+ {2723, {wxLayoutAlgorithm, layoutMDIFrame, 2}},
+ {2724, {wxLayoutAlgorithm, layoutWindow, 2}},
+ {2725, {wxLayoutAlgorithm, 'Destroy', undefined}},
+ {2726, {wxEvent, getId, 0}},
+ {2727, {wxEvent, getSkipped, 0}},
+ {2728, {wxEvent, getTimestamp, 0}},
+ {2729, {wxEvent, isCommandEvent, 0}},
+ {2730, {wxEvent, resumePropagation, 1}},
+ {2731, {wxEvent, shouldPropagate, 0}},
+ {2732, {wxEvent, skip, 1}},
+ {2733, {wxEvent, stopPropagation, 0}},
+ {2734, {wxCommandEvent, getClientData, 0}},
+ {2735, {wxCommandEvent, getExtraLong, 0}},
+ {2736, {wxCommandEvent, getInt, 0}},
+ {2737, {wxCommandEvent, getSelection, 0}},
+ {2738, {wxCommandEvent, getString, 0}},
+ {2739, {wxCommandEvent, isChecked, 0}},
+ {2740, {wxCommandEvent, isSelection, 0}},
+ {2741, {wxCommandEvent, setInt, 1}},
+ {2742, {wxCommandEvent, setString, 1}},
+ {2743, {wxScrollEvent, getOrientation, 0}},
+ {2744, {wxScrollEvent, getPosition, 0}},
+ {2745, {wxScrollWinEvent, getOrientation, 0}},
+ {2746, {wxScrollWinEvent, getPosition, 0}},
+ {2747, {wxMouseEvent, altDown, 0}},
+ {2748, {wxMouseEvent, button, 1}},
+ {2749, {wxMouseEvent, buttonDClick, 1}},
+ {2750, {wxMouseEvent, buttonDown, 1}},
+ {2751, {wxMouseEvent, buttonUp, 1}},
+ {2752, {wxMouseEvent, cmdDown, 0}},
+ {2753, {wxMouseEvent, controlDown, 0}},
+ {2754, {wxMouseEvent, dragging, 0}},
+ {2755, {wxMouseEvent, entering, 0}},
+ {2756, {wxMouseEvent, getButton, 0}},
+ {2759, {wxMouseEvent, getPosition, 0}},
+ {2760, {wxMouseEvent, getLogicalPosition, 1}},
+ {2761, {wxMouseEvent, getLinesPerAction, 0}},
+ {2762, {wxMouseEvent, getWheelRotation, 0}},
+ {2763, {wxMouseEvent, getWheelDelta, 0}},
+ {2764, {wxMouseEvent, getX, 0}},
+ {2765, {wxMouseEvent, getY, 0}},
+ {2766, {wxMouseEvent, isButton, 0}},
+ {2767, {wxMouseEvent, isPageScroll, 0}},
+ {2768, {wxMouseEvent, leaving, 0}},
+ {2769, {wxMouseEvent, leftDClick, 0}},
+ {2770, {wxMouseEvent, leftDown, 0}},
+ {2771, {wxMouseEvent, leftIsDown, 0}},
+ {2772, {wxMouseEvent, leftUp, 0}},
+ {2773, {wxMouseEvent, metaDown, 0}},
+ {2774, {wxMouseEvent, middleDClick, 0}},
+ {2775, {wxMouseEvent, middleDown, 0}},
+ {2776, {wxMouseEvent, middleIsDown, 0}},
+ {2777, {wxMouseEvent, middleUp, 0}},
+ {2778, {wxMouseEvent, moving, 0}},
+ {2779, {wxMouseEvent, rightDClick, 0}},
+ {2780, {wxMouseEvent, rightDown, 0}},
+ {2781, {wxMouseEvent, rightIsDown, 0}},
+ {2782, {wxMouseEvent, rightUp, 0}},
+ {2783, {wxMouseEvent, shiftDown, 0}},
+ {2784, {wxSetCursorEvent, getCursor, 0}},
+ {2785, {wxSetCursorEvent, getX, 0}},
+ {2786, {wxSetCursorEvent, getY, 0}},
+ {2787, {wxSetCursorEvent, hasCursor, 0}},
+ {2788, {wxSetCursorEvent, setCursor, 1}},
+ {2789, {wxKeyEvent, altDown, 0}},
+ {2790, {wxKeyEvent, cmdDown, 0}},
+ {2791, {wxKeyEvent, controlDown, 0}},
+ {2792, {wxKeyEvent, getKeyCode, 0}},
+ {2793, {wxKeyEvent, getModifiers, 0}},
+ {2796, {wxKeyEvent, getPosition, 0}},
+ {2797, {wxKeyEvent, getRawKeyCode, 0}},
+ {2798, {wxKeyEvent, getRawKeyFlags, 0}},
+ {2799, {wxKeyEvent, getUnicodeKey, 0}},
+ {2800, {wxKeyEvent, getX, 0}},
+ {2801, {wxKeyEvent, getY, 0}},
+ {2802, {wxKeyEvent, hasModifiers, 0}},
+ {2803, {wxKeyEvent, metaDown, 0}},
+ {2804, {wxKeyEvent, shiftDown, 0}},
+ {2805, {wxSizeEvent, getSize, 0}},
+ {2806, {wxMoveEvent, getPosition, 0}},
+ {2807, {wxEraseEvent, getDC, 0}},
+ {2808, {wxFocusEvent, getWindow, 0}},
+ {2809, {wxChildFocusEvent, getWindow, 0}},
+ {2810, {wxMenuEvent, getMenu, 0}},
+ {2811, {wxMenuEvent, getMenuId, 0}},
+ {2812, {wxMenuEvent, isPopup, 0}},
+ {2813, {wxCloseEvent, canVeto, 0}},
+ {2814, {wxCloseEvent, getLoggingOff, 0}},
+ {2815, {wxCloseEvent, setCanVeto, 1}},
+ {2816, {wxCloseEvent, setLoggingOff, 1}},
+ {2817, {wxCloseEvent, veto, 1}},
+ {2818, {wxShowEvent, setShow, 1}},
+ {2819, {wxShowEvent, getShow, 0}},
+ {2820, {wxIconizeEvent, iconized, 0}},
+ {2821, {wxJoystickEvent, buttonDown, 1}},
+ {2822, {wxJoystickEvent, buttonIsDown, 1}},
+ {2823, {wxJoystickEvent, buttonUp, 1}},
+ {2824, {wxJoystickEvent, getButtonChange, 0}},
+ {2825, {wxJoystickEvent, getButtonState, 0}},
+ {2826, {wxJoystickEvent, getJoystick, 0}},
+ {2827, {wxJoystickEvent, getPosition, 0}},
+ {2828, {wxJoystickEvent, getZPosition, 0}},
+ {2829, {wxJoystickEvent, isButton, 0}},
+ {2830, {wxJoystickEvent, isMove, 0}},
+ {2831, {wxJoystickEvent, isZMove, 0}},
+ {2832, {wxUpdateUIEvent, canUpdate, 1}},
+ {2833, {wxUpdateUIEvent, check, 1}},
+ {2834, {wxUpdateUIEvent, enable, 1}},
+ {2835, {wxUpdateUIEvent, show, 1}},
+ {2836, {wxUpdateUIEvent, getChecked, 0}},
+ {2837, {wxUpdateUIEvent, getEnabled, 0}},
+ {2838, {wxUpdateUIEvent, getShown, 0}},
+ {2839, {wxUpdateUIEvent, getSetChecked, 0}},
+ {2840, {wxUpdateUIEvent, getSetEnabled, 0}},
+ {2841, {wxUpdateUIEvent, getSetShown, 0}},
+ {2842, {wxUpdateUIEvent, getSetText, 0}},
+ {2843, {wxUpdateUIEvent, getText, 0}},
+ {2844, {wxUpdateUIEvent, getMode, 0}},
+ {2845, {wxUpdateUIEvent, getUpdateInterval, 0}},
+ {2846, {wxUpdateUIEvent, resetUpdateTime, 0}},
+ {2847, {wxUpdateUIEvent, setMode, 1}},
+ {2848, {wxUpdateUIEvent, setText, 1}},
+ {2849, {wxUpdateUIEvent, setUpdateInterval, 1}},
+ {2850, {wxMouseCaptureChangedEvent, getCapturedWindow, 0}},
+ {2851, {wxPaletteChangedEvent, setChangedWindow, 1}},
+ {2852, {wxPaletteChangedEvent, getChangedWindow, 0}},
+ {2853, {wxQueryNewPaletteEvent, setPaletteRealized, 1}},
+ {2854, {wxQueryNewPaletteEvent, getPaletteRealized, 0}},
+ {2855, {wxNavigationKeyEvent, getDirection, 0}},
+ {2856, {wxNavigationKeyEvent, setDirection, 1}},
+ {2857, {wxNavigationKeyEvent, isWindowChange, 0}},
+ {2858, {wxNavigationKeyEvent, setWindowChange, 1}},
+ {2859, {wxNavigationKeyEvent, isFromTab, 0}},
+ {2860, {wxNavigationKeyEvent, setFromTab, 1}},
+ {2861, {wxNavigationKeyEvent, getCurrentFocus, 0}},
+ {2862, {wxNavigationKeyEvent, setCurrentFocus, 1}},
+ {2863, {wxHelpEvent, getOrigin, 0}},
+ {2864, {wxHelpEvent, getPosition, 0}},
+ {2865, {wxHelpEvent, setOrigin, 1}},
+ {2866, {wxHelpEvent, setPosition, 1}},
+ {2867, {wxContextMenuEvent, getPosition, 0}},
+ {2868, {wxContextMenuEvent, setPosition, 1}},
+ {2869, {wxIdleEvent, canSend, 1}},
+ {2870, {wxIdleEvent, getMode, 0}},
+ {2871, {wxIdleEvent, requestMore, 1}},
+ {2872, {wxIdleEvent, moreRequested, 0}},
+ {2873, {wxIdleEvent, setMode, 1}},
+ {2874, {wxGridEvent, altDown, 0}},
+ {2875, {wxGridEvent, controlDown, 0}},
+ {2876, {wxGridEvent, getCol, 0}},
+ {2877, {wxGridEvent, getPosition, 0}},
+ {2878, {wxGridEvent, getRow, 0}},
+ {2879, {wxGridEvent, metaDown, 0}},
+ {2880, {wxGridEvent, selecting, 0}},
+ {2881, {wxGridEvent, shiftDown, 0}},
+ {2882, {wxNotifyEvent, allow, 0}},
+ {2883, {wxNotifyEvent, isAllowed, 0}},
+ {2884, {wxNotifyEvent, veto, 0}},
+ {2885, {wxSashEvent, getEdge, 0}},
+ {2886, {wxSashEvent, getDragRect, 0}},
+ {2887, {wxSashEvent, getDragStatus, 0}},
+ {2888, {wxListEvent, getCacheFrom, 0}},
+ {2889, {wxListEvent, getCacheTo, 0}},
+ {2890, {wxListEvent, getKeyCode, 0}},
+ {2891, {wxListEvent, getIndex, 0}},
+ {2892, {wxListEvent, getColumn, 0}},
+ {2893, {wxListEvent, getPoint, 0}},
+ {2894, {wxListEvent, getLabel, 0}},
+ {2895, {wxListEvent, getText, 0}},
+ {2896, {wxListEvent, getImage, 0}},
+ {2897, {wxListEvent, getData, 0}},
+ {2898, {wxListEvent, getMask, 0}},
+ {2899, {wxListEvent, getItem, 0}},
+ {2900, {wxListEvent, isEditCancelled, 0}},
+ {2901, {wxDateEvent, getDate, 0}},
+ {2902, {wxCalendarEvent, getWeekDay, 0}},
+ {2903, {wxFileDirPickerEvent, getPath, 0}},
+ {2904, {wxColourPickerEvent, getColour, 0}},
+ {2905, {wxFontPickerEvent, getFont, 0}},
+ {2906, {wxStyledTextEvent, getPosition, 0}},
+ {2907, {wxStyledTextEvent, getKey, 0}},
+ {2908, {wxStyledTextEvent, getModifiers, 0}},
+ {2909, {wxStyledTextEvent, getModificationType, 0}},
+ {2910, {wxStyledTextEvent, getText, 0}},
+ {2911, {wxStyledTextEvent, getLength, 0}},
+ {2912, {wxStyledTextEvent, getLinesAdded, 0}},
+ {2913, {wxStyledTextEvent, getLine, 0}},
+ {2914, {wxStyledTextEvent, getFoldLevelNow, 0}},
+ {2915, {wxStyledTextEvent, getFoldLevelPrev, 0}},
+ {2916, {wxStyledTextEvent, getMargin, 0}},
+ {2917, {wxStyledTextEvent, getMessage, 0}},
+ {2918, {wxStyledTextEvent, getWParam, 0}},
+ {2919, {wxStyledTextEvent, getLParam, 0}},
+ {2920, {wxStyledTextEvent, getListType, 0}},
+ {2921, {wxStyledTextEvent, getX, 0}},
+ {2922, {wxStyledTextEvent, getY, 0}},
+ {2923, {wxStyledTextEvent, getDragText, 0}},
+ {2924, {wxStyledTextEvent, getDragAllowMove, 0}},
+ {2925, {wxStyledTextEvent, getDragResult, 0}},
+ {2926, {wxStyledTextEvent, getShift, 0}},
+ {2927, {wxStyledTextEvent, getControl, 0}},
+ {2928, {wxStyledTextEvent, getAlt, 0}},
+ {2929, {utils, getKeyState, 1}},
+ {2930, {utils, getMousePosition, 2}},
+ {2931, {utils, getMouseState, 0}},
+ {2932, {utils, setDetectableAutoRepeat, 1}},
+ {2933, {utils, bell, 0}},
+ {2934, {utils, findMenuItemId, 3}},
+ {2935, {utils, genericFindWindowAtPoint, 1}},
+ {2936, {utils, findWindowAtPoint, 1}},
+ {2937, {utils, beginBusyCursor, 1}},
+ {2938, {utils, endBusyCursor, 0}},
+ {2939, {utils, isBusy, 0}},
+ {2940, {utils, shutdown, 1}},
+ {2941, {utils, shell, 1}},
+ {2942, {utils, launchDefaultBrowser, 2}},
+ {2943, {utils, getEmailAddress, 0}},
+ {2944, {utils, getUserId, 0}},
+ {2945, {utils, getHomeDir, 0}},
+ {2946, {utils, newId, 0}},
+ {2947, {utils, registerId, 1}},
+ {2948, {utils, getCurrentId, 0}},
+ {2949, {utils, getOsDescription, 0}},
+ {2950, {utils, isPlatformLittleEndian, 0}},
+ {2951, {utils, isPlatform64Bit, 0}},
+ {2952, {gdicmn, displaySize, 2}},
+ {2953, {gdicmn, setCursor, 1}},
+ {2954, {wxPrintout, new, 1}},
+ {2955, {wxPrintout, destruct, 0}},
+ {2956, {wxPrintout, getDC, 0}},
+ {2957, {wxPrintout, getPageSizeMM, 2}},
+ {2958, {wxPrintout, getPageSizePixels, 2}},
+ {2959, {wxPrintout, getPaperRectPixels, 0}},
+ {2960, {wxPrintout, getPPIPrinter, 2}},
+ {2961, {wxPrintout, getPPIScreen, 2}},
+ {2962, {wxPrintout, getTitle, 0}},
+ {2963, {wxPrintout, isPreview, 0}},
+ {2964, {wxPrintout, fitThisSizeToPaper, 1}},
+ {2965, {wxPrintout, fitThisSizeToPage, 1}},
+ {2966, {wxPrintout, fitThisSizeToPageMargins, 2}},
+ {2967, {wxPrintout, mapScreenSizeToPaper, 0}},
+ {2968, {wxPrintout, mapScreenSizeToPage, 0}},
+ {2969, {wxPrintout, mapScreenSizeToPageMargins, 1}},
+ {2970, {wxPrintout, mapScreenSizeToDevice, 0}},
+ {2971, {wxPrintout, getLogicalPaperRect, 0}},
+ {2972, {wxPrintout, getLogicalPageRect, 0}},
+ {2973, {wxPrintout, getLogicalPageMarginsRect, 1}},
+ {2974, {wxPrintout, setLogicalOrigin, 2}},
+ {2975, {wxPrintout, offsetLogicalOrigin, 2}},
+ {2976, {wxStyledTextCtrl, new_2, 2}},
+ {2977, {wxStyledTextCtrl, new_0, 0}},
+ {2978, {wxStyledTextCtrl, destruct, 0}},
+ {2979, {wxStyledTextCtrl, create, 2}},
+ {2980, {wxStyledTextCtrl, addText, 1}},
+ {2981, {wxStyledTextCtrl, addStyledText, 1}},
+ {2982, {wxStyledTextCtrl, insertText, 2}},
+ {2983, {wxStyledTextCtrl, clearAll, 0}},
+ {2984, {wxStyledTextCtrl, clearDocumentStyle, 0}},
+ {2985, {wxStyledTextCtrl, getLength, 0}},
+ {2986, {wxStyledTextCtrl, getCharAt, 1}},
+ {2987, {wxStyledTextCtrl, getCurrentPos, 0}},
+ {2988, {wxStyledTextCtrl, getAnchor, 0}},
+ {2989, {wxStyledTextCtrl, getStyleAt, 1}},
+ {2990, {wxStyledTextCtrl, redo, 0}},
+ {2991, {wxStyledTextCtrl, setUndoCollection, 1}},
+ {2992, {wxStyledTextCtrl, selectAll, 0}},
+ {2993, {wxStyledTextCtrl, setSavePoint, 0}},
+ {2994, {wxStyledTextCtrl, getStyledText, 2}},
+ {2995, {wxStyledTextCtrl, canRedo, 0}},
+ {2996, {wxStyledTextCtrl, markerLineFromHandle, 1}},
+ {2997, {wxStyledTextCtrl, markerDeleteHandle, 1}},
+ {2998, {wxStyledTextCtrl, getUndoCollection, 0}},
+ {2999, {wxStyledTextCtrl, getViewWhiteSpace, 0}},
+ {3000, {wxStyledTextCtrl, setViewWhiteSpace, 1}},
+ {3001, {wxStyledTextCtrl, positionFromPoint, 1}},
+ {3002, {wxStyledTextCtrl, positionFromPointClose, 2}},
+ {3003, {wxStyledTextCtrl, gotoLine, 1}},
+ {3004, {wxStyledTextCtrl, gotoPos, 1}},
+ {3005, {wxStyledTextCtrl, setAnchor, 1}},
+ {3006, {wxStyledTextCtrl, getCurLine, 1}},
+ {3007, {wxStyledTextCtrl, getEndStyled, 0}},
+ {3008, {wxStyledTextCtrl, convertEOLs, 1}},
+ {3009, {wxStyledTextCtrl, getEOLMode, 0}},
+ {3010, {wxStyledTextCtrl, setEOLMode, 1}},
+ {3011, {wxStyledTextCtrl, startStyling, 2}},
+ {3012, {wxStyledTextCtrl, setStyling, 2}},
+ {3013, {wxStyledTextCtrl, getBufferedDraw, 0}},
+ {3014, {wxStyledTextCtrl, setBufferedDraw, 1}},
+ {3015, {wxStyledTextCtrl, setTabWidth, 1}},
+ {3016, {wxStyledTextCtrl, getTabWidth, 0}},
+ {3017, {wxStyledTextCtrl, setCodePage, 1}},
+ {3018, {wxStyledTextCtrl, markerDefine, 3}},
+ {3019, {wxStyledTextCtrl, markerSetForeground, 2}},
+ {3020, {wxStyledTextCtrl, markerSetBackground, 2}},
+ {3021, {wxStyledTextCtrl, markerAdd, 2}},
+ {3022, {wxStyledTextCtrl, markerDelete, 2}},
+ {3023, {wxStyledTextCtrl, markerDeleteAll, 1}},
+ {3024, {wxStyledTextCtrl, markerGet, 1}},
+ {3025, {wxStyledTextCtrl, markerNext, 2}},
+ {3026, {wxStyledTextCtrl, markerPrevious, 2}},
+ {3027, {wxStyledTextCtrl, markerDefineBitmap, 2}},
+ {3028, {wxStyledTextCtrl, markerAddSet, 2}},
+ {3029, {wxStyledTextCtrl, markerSetAlpha, 2}},
+ {3030, {wxStyledTextCtrl, setMarginType, 2}},
+ {3031, {wxStyledTextCtrl, getMarginType, 1}},
+ {3032, {wxStyledTextCtrl, setMarginWidth, 2}},
+ {3033, {wxStyledTextCtrl, getMarginWidth, 1}},
+ {3034, {wxStyledTextCtrl, setMarginMask, 2}},
+ {3035, {wxStyledTextCtrl, getMarginMask, 1}},
+ {3036, {wxStyledTextCtrl, setMarginSensitive, 2}},
+ {3037, {wxStyledTextCtrl, getMarginSensitive, 1}},
+ {3038, {wxStyledTextCtrl, styleClearAll, 0}},
+ {3039, {wxStyledTextCtrl, styleSetForeground, 2}},
+ {3040, {wxStyledTextCtrl, styleSetBackground, 2}},
+ {3041, {wxStyledTextCtrl, styleSetBold, 2}},
+ {3042, {wxStyledTextCtrl, styleSetItalic, 2}},
+ {3043, {wxStyledTextCtrl, styleSetSize, 2}},
+ {3044, {wxStyledTextCtrl, styleSetFaceName, 2}},
+ {3045, {wxStyledTextCtrl, styleSetEOLFilled, 2}},
+ {3046, {wxStyledTextCtrl, styleResetDefault, 0}},
+ {3047, {wxStyledTextCtrl, styleSetUnderline, 2}},
+ {3048, {wxStyledTextCtrl, styleSetCase, 2}},
+ {3049, {wxStyledTextCtrl, styleSetHotSpot, 2}},
+ {3050, {wxStyledTextCtrl, setSelForeground, 2}},
+ {3051, {wxStyledTextCtrl, setSelBackground, 2}},
+ {3052, {wxStyledTextCtrl, getSelAlpha, 0}},
+ {3053, {wxStyledTextCtrl, setSelAlpha, 1}},
+ {3054, {wxStyledTextCtrl, setCaretForeground, 1}},
+ {3055, {wxStyledTextCtrl, cmdKeyAssign, 3}},
+ {3056, {wxStyledTextCtrl, cmdKeyClear, 2}},
+ {3057, {wxStyledTextCtrl, cmdKeyClearAll, 0}},
+ {3058, {wxStyledTextCtrl, setStyleBytes, 2}},
+ {3059, {wxStyledTextCtrl, styleSetVisible, 2}},
+ {3060, {wxStyledTextCtrl, getCaretPeriod, 0}},
+ {3061, {wxStyledTextCtrl, setCaretPeriod, 1}},
+ {3062, {wxStyledTextCtrl, setWordChars, 1}},
+ {3063, {wxStyledTextCtrl, beginUndoAction, 0}},
+ {3064, {wxStyledTextCtrl, endUndoAction, 0}},
+ {3065, {wxStyledTextCtrl, indicatorSetStyle, 2}},
+ {3066, {wxStyledTextCtrl, indicatorGetStyle, 1}},
+ {3067, {wxStyledTextCtrl, indicatorSetForeground, 2}},
+ {3068, {wxStyledTextCtrl, indicatorGetForeground, 1}},
+ {3069, {wxStyledTextCtrl, setWhitespaceForeground, 2}},
+ {3070, {wxStyledTextCtrl, setWhitespaceBackground, 2}},
+ {3071, {wxStyledTextCtrl, getStyleBits, 0}},
+ {3072, {wxStyledTextCtrl, setLineState, 2}},
+ {3073, {wxStyledTextCtrl, getLineState, 1}},
+ {3074, {wxStyledTextCtrl, getMaxLineState, 0}},
+ {3075, {wxStyledTextCtrl, getCaretLineVisible, 0}},
+ {3076, {wxStyledTextCtrl, setCaretLineVisible, 1}},
+ {3077, {wxStyledTextCtrl, getCaretLineBackground, 0}},
+ {3078, {wxStyledTextCtrl, setCaretLineBackground, 1}},
+ {3079, {wxStyledTextCtrl, autoCompShow, 2}},
+ {3080, {wxStyledTextCtrl, autoCompCancel, 0}},
+ {3081, {wxStyledTextCtrl, autoCompActive, 0}},
+ {3082, {wxStyledTextCtrl, autoCompPosStart, 0}},
+ {3083, {wxStyledTextCtrl, autoCompComplete, 0}},
+ {3084, {wxStyledTextCtrl, autoCompStops, 1}},
+ {3085, {wxStyledTextCtrl, autoCompSetSeparator, 1}},
+ {3086, {wxStyledTextCtrl, autoCompGetSeparator, 0}},
+ {3087, {wxStyledTextCtrl, autoCompSelect, 1}},
+ {3088, {wxStyledTextCtrl, autoCompSetCancelAtStart, 1}},
+ {3089, {wxStyledTextCtrl, autoCompGetCancelAtStart, 0}},
+ {3090, {wxStyledTextCtrl, autoCompSetFillUps, 1}},
+ {3091, {wxStyledTextCtrl, autoCompSetChooseSingle, 1}},
+ {3092, {wxStyledTextCtrl, autoCompGetChooseSingle, 0}},
+ {3093, {wxStyledTextCtrl, autoCompSetIgnoreCase, 1}},
+ {3094, {wxStyledTextCtrl, autoCompGetIgnoreCase, 0}},
+ {3095, {wxStyledTextCtrl, userListShow, 2}},
+ {3096, {wxStyledTextCtrl, autoCompSetAutoHide, 1}},
+ {3097, {wxStyledTextCtrl, autoCompGetAutoHide, 0}},
+ {3098, {wxStyledTextCtrl, autoCompSetDropRestOfWord, 1}},
+ {3099, {wxStyledTextCtrl, autoCompGetDropRestOfWord, 0}},
+ {3100, {wxStyledTextCtrl, registerImage, 2}},
+ {3101, {wxStyledTextCtrl, clearRegisteredImages, 0}},
+ {3102, {wxStyledTextCtrl, autoCompGetTypeSeparator, 0}},
+ {3103, {wxStyledTextCtrl, autoCompSetTypeSeparator, 1}},
+ {3104, {wxStyledTextCtrl, autoCompSetMaxWidth, 1}},
+ {3105, {wxStyledTextCtrl, autoCompGetMaxWidth, 0}},
+ {3106, {wxStyledTextCtrl, autoCompSetMaxHeight, 1}},
+ {3107, {wxStyledTextCtrl, autoCompGetMaxHeight, 0}},
+ {3108, {wxStyledTextCtrl, setIndent, 1}},
+ {3109, {wxStyledTextCtrl, getIndent, 0}},
+ {3110, {wxStyledTextCtrl, setUseTabs, 1}},
+ {3111, {wxStyledTextCtrl, getUseTabs, 0}},
+ {3112, {wxStyledTextCtrl, setLineIndentation, 2}},
+ {3113, {wxStyledTextCtrl, getLineIndentation, 1}},
+ {3114, {wxStyledTextCtrl, getLineIndentPosition, 1}},
+ {3115, {wxStyledTextCtrl, getColumn, 1}},
+ {3116, {wxStyledTextCtrl, setUseHorizontalScrollBar, 1}},
+ {3117, {wxStyledTextCtrl, getUseHorizontalScrollBar, 0}},
+ {3118, {wxStyledTextCtrl, setIndentationGuides, 1}},
+ {3119, {wxStyledTextCtrl, getIndentationGuides, 0}},
+ {3120, {wxStyledTextCtrl, setHighlightGuide, 1}},
+ {3121, {wxStyledTextCtrl, getHighlightGuide, 0}},
+ {3122, {wxStyledTextCtrl, getLineEndPosition, 1}},
+ {3123, {wxStyledTextCtrl, getCodePage, 0}},
+ {3124, {wxStyledTextCtrl, getCaretForeground, 0}},
+ {3125, {wxStyledTextCtrl, getReadOnly, 0}},
+ {3126, {wxStyledTextCtrl, setCurrentPos, 1}},
+ {3127, {wxStyledTextCtrl, setSelectionStart, 1}},
+ {3128, {wxStyledTextCtrl, getSelectionStart, 0}},
+ {3129, {wxStyledTextCtrl, setSelectionEnd, 1}},
+ {3130, {wxStyledTextCtrl, getSelectionEnd, 0}},
+ {3131, {wxStyledTextCtrl, setPrintMagnification, 1}},
+ {3132, {wxStyledTextCtrl, getPrintMagnification, 0}},
+ {3133, {wxStyledTextCtrl, setPrintColourMode, 1}},
+ {3134, {wxStyledTextCtrl, getPrintColourMode, 0}},
+ {3135, {wxStyledTextCtrl, findText, 4}},
+ {3136, {wxStyledTextCtrl, formatRange, 7}},
+ {3137, {wxStyledTextCtrl, getFirstVisibleLine, 0}},
+ {3138, {wxStyledTextCtrl, getLine, 1}},
+ {3139, {wxStyledTextCtrl, getLineCount, 0}},
+ {3140, {wxStyledTextCtrl, setMarginLeft, 1}},
+ {3141, {wxStyledTextCtrl, getMarginLeft, 0}},
+ {3142, {wxStyledTextCtrl, setMarginRight, 1}},
+ {3143, {wxStyledTextCtrl, getMarginRight, 0}},
+ {3144, {wxStyledTextCtrl, getModify, 0}},
+ {3145, {wxStyledTextCtrl, setSelection, 2}},
+ {3146, {wxStyledTextCtrl, getSelectedText, 0}},
+ {3147, {wxStyledTextCtrl, getTextRange, 2}},
+ {3148, {wxStyledTextCtrl, hideSelection, 1}},
+ {3149, {wxStyledTextCtrl, lineFromPosition, 1}},
+ {3150, {wxStyledTextCtrl, positionFromLine, 1}},
+ {3151, {wxStyledTextCtrl, lineScroll, 2}},
+ {3152, {wxStyledTextCtrl, ensureCaretVisible, 0}},
+ {3153, {wxStyledTextCtrl, replaceSelection, 1}},
+ {3154, {wxStyledTextCtrl, setReadOnly, 1}},
+ {3155, {wxStyledTextCtrl, canPaste, 0}},
+ {3156, {wxStyledTextCtrl, canUndo, 0}},
+ {3157, {wxStyledTextCtrl, emptyUndoBuffer, 0}},
+ {3158, {wxStyledTextCtrl, undo, 0}},
+ {3159, {wxStyledTextCtrl, cut, 0}},
+ {3160, {wxStyledTextCtrl, copy, 0}},
+ {3161, {wxStyledTextCtrl, paste, 0}},
+ {3162, {wxStyledTextCtrl, clear, 0}},
+ {3163, {wxStyledTextCtrl, setText, 1}},
+ {3164, {wxStyledTextCtrl, getText, 0}},
+ {3165, {wxStyledTextCtrl, getTextLength, 0}},
+ {3166, {wxStyledTextCtrl, getOvertype, 0}},
+ {3167, {wxStyledTextCtrl, setCaretWidth, 1}},
+ {3168, {wxStyledTextCtrl, getCaretWidth, 0}},
+ {3169, {wxStyledTextCtrl, setTargetStart, 1}},
+ {3170, {wxStyledTextCtrl, getTargetStart, 0}},
+ {3171, {wxStyledTextCtrl, setTargetEnd, 1}},
+ {3172, {wxStyledTextCtrl, getTargetEnd, 0}},
+ {3173, {wxStyledTextCtrl, replaceTarget, 1}},
+ {3174, {wxStyledTextCtrl, searchInTarget, 1}},
+ {3175, {wxStyledTextCtrl, setSearchFlags, 1}},
+ {3176, {wxStyledTextCtrl, getSearchFlags, 0}},
+ {3177, {wxStyledTextCtrl, callTipShow, 2}},
+ {3178, {wxStyledTextCtrl, callTipCancel, 0}},
+ {3179, {wxStyledTextCtrl, callTipActive, 0}},
+ {3180, {wxStyledTextCtrl, callTipPosAtStart, 0}},
+ {3181, {wxStyledTextCtrl, callTipSetHighlight, 2}},
+ {3182, {wxStyledTextCtrl, callTipSetBackground, 1}},
+ {3183, {wxStyledTextCtrl, callTipSetForeground, 1}},
+ {3184, {wxStyledTextCtrl, callTipSetForegroundHighlight, 1}},
+ {3185, {wxStyledTextCtrl, callTipUseStyle, 1}},
+ {3186, {wxStyledTextCtrl, visibleFromDocLine, 1}},
+ {3187, {wxStyledTextCtrl, docLineFromVisible, 1}},
+ {3188, {wxStyledTextCtrl, wrapCount, 1}},
+ {3189, {wxStyledTextCtrl, setFoldLevel, 2}},
+ {3190, {wxStyledTextCtrl, getFoldLevel, 1}},
+ {3191, {wxStyledTextCtrl, getLastChild, 2}},
+ {3192, {wxStyledTextCtrl, getFoldParent, 1}},
+ {3193, {wxStyledTextCtrl, showLines, 2}},
+ {3194, {wxStyledTextCtrl, hideLines, 2}},
+ {3195, {wxStyledTextCtrl, getLineVisible, 1}},
+ {3196, {wxStyledTextCtrl, setFoldExpanded, 2}},
+ {3197, {wxStyledTextCtrl, getFoldExpanded, 1}},
+ {3198, {wxStyledTextCtrl, toggleFold, 1}},
+ {3199, {wxStyledTextCtrl, ensureVisible, 1}},
+ {3200, {wxStyledTextCtrl, setFoldFlags, 1}},
+ {3201, {wxStyledTextCtrl, ensureVisibleEnforcePolicy, 1}},
+ {3202, {wxStyledTextCtrl, setTabIndents, 1}},
+ {3203, {wxStyledTextCtrl, getTabIndents, 0}},
+ {3204, {wxStyledTextCtrl, setBackSpaceUnIndents, 1}},
+ {3205, {wxStyledTextCtrl, getBackSpaceUnIndents, 0}},
+ {3206, {wxStyledTextCtrl, setMouseDwellTime, 1}},
+ {3207, {wxStyledTextCtrl, getMouseDwellTime, 0}},
+ {3208, {wxStyledTextCtrl, wordStartPosition, 2}},
+ {3209, {wxStyledTextCtrl, wordEndPosition, 2}},
+ {3210, {wxStyledTextCtrl, setWrapMode, 1}},
+ {3211, {wxStyledTextCtrl, getWrapMode, 0}},
+ {3212, {wxStyledTextCtrl, setWrapVisualFlags, 1}},
+ {3213, {wxStyledTextCtrl, getWrapVisualFlags, 0}},
+ {3214, {wxStyledTextCtrl, setWrapVisualFlagsLocation, 1}},
+ {3215, {wxStyledTextCtrl, getWrapVisualFlagsLocation, 0}},
+ {3216, {wxStyledTextCtrl, setWrapStartIndent, 1}},
+ {3217, {wxStyledTextCtrl, getWrapStartIndent, 0}},
+ {3218, {wxStyledTextCtrl, setLayoutCache, 1}},
+ {3219, {wxStyledTextCtrl, getLayoutCache, 0}},
+ {3220, {wxStyledTextCtrl, setScrollWidth, 1}},
+ {3221, {wxStyledTextCtrl, getScrollWidth, 0}},
+ {3222, {wxStyledTextCtrl, textWidth, 2}},
+ {3223, {wxStyledTextCtrl, getEndAtLastLine, 0}},
+ {3224, {wxStyledTextCtrl, textHeight, 1}},
+ {3225, {wxStyledTextCtrl, setUseVerticalScrollBar, 1}},
+ {3226, {wxStyledTextCtrl, getUseVerticalScrollBar, 0}},
+ {3227, {wxStyledTextCtrl, appendText, 1}},
+ {3228, {wxStyledTextCtrl, getTwoPhaseDraw, 0}},
+ {3229, {wxStyledTextCtrl, setTwoPhaseDraw, 1}},
+ {3230, {wxStyledTextCtrl, targetFromSelection, 0}},
+ {3231, {wxStyledTextCtrl, linesJoin, 0}},
+ {3232, {wxStyledTextCtrl, linesSplit, 1}},
+ {3233, {wxStyledTextCtrl, setFoldMarginColour, 2}},
+ {3234, {wxStyledTextCtrl, setFoldMarginHiColour, 2}},
+ {3235, {wxStyledTextCtrl, lineDown, 0}},
+ {3236, {wxStyledTextCtrl, lineDownExtend, 0}},
+ {3237, {wxStyledTextCtrl, lineUp, 0}},
+ {3238, {wxStyledTextCtrl, lineUpExtend, 0}},
+ {3239, {wxStyledTextCtrl, charLeft, 0}},
+ {3240, {wxStyledTextCtrl, charLeftExtend, 0}},
+ {3241, {wxStyledTextCtrl, charRight, 0}},
+ {3242, {wxStyledTextCtrl, charRightExtend, 0}},
+ {3243, {wxStyledTextCtrl, wordLeft, 0}},
+ {3244, {wxStyledTextCtrl, wordLeftExtend, 0}},
+ {3245, {wxStyledTextCtrl, wordRight, 0}},
+ {3246, {wxStyledTextCtrl, wordRightExtend, 0}},
+ {3247, {wxStyledTextCtrl, home, 0}},
+ {3248, {wxStyledTextCtrl, homeExtend, 0}},
+ {3249, {wxStyledTextCtrl, lineEnd, 0}},
+ {3250, {wxStyledTextCtrl, lineEndExtend, 0}},
+ {3251, {wxStyledTextCtrl, documentStart, 0}},
+ {3252, {wxStyledTextCtrl, documentStartExtend, 0}},
+ {3253, {wxStyledTextCtrl, documentEnd, 0}},
+ {3254, {wxStyledTextCtrl, documentEndExtend, 0}},
+ {3255, {wxStyledTextCtrl, pageUp, 0}},
+ {3256, {wxStyledTextCtrl, pageUpExtend, 0}},
+ {3257, {wxStyledTextCtrl, pageDown, 0}},
+ {3258, {wxStyledTextCtrl, pageDownExtend, 0}},
+ {3259, {wxStyledTextCtrl, editToggleOvertype, 0}},
+ {3260, {wxStyledTextCtrl, cancel, 0}},
+ {3261, {wxStyledTextCtrl, deleteBack, 0}},
+ {3262, {wxStyledTextCtrl, tab, 0}},
+ {3263, {wxStyledTextCtrl, backTab, 0}},
+ {3264, {wxStyledTextCtrl, newLine, 0}},
+ {3265, {wxStyledTextCtrl, formFeed, 0}},
+ {3266, {wxStyledTextCtrl, vCHome, 0}},
+ {3267, {wxStyledTextCtrl, vCHomeExtend, 0}},
+ {3268, {wxStyledTextCtrl, zoomIn, 0}},
+ {3269, {wxStyledTextCtrl, zoomOut, 0}},
+ {3270, {wxStyledTextCtrl, delWordLeft, 0}},
+ {3271, {wxStyledTextCtrl, delWordRight, 0}},
+ {3272, {wxStyledTextCtrl, lineCut, 0}},
+ {3273, {wxStyledTextCtrl, lineDelete, 0}},
+ {3274, {wxStyledTextCtrl, lineTranspose, 0}},
+ {3275, {wxStyledTextCtrl, lineDuplicate, 0}},
+ {3276, {wxStyledTextCtrl, lowerCase, 0}},
+ {3277, {wxStyledTextCtrl, upperCase, 0}},
+ {3278, {wxStyledTextCtrl, lineScrollDown, 0}},
+ {3279, {wxStyledTextCtrl, lineScrollUp, 0}},
+ {3280, {wxStyledTextCtrl, deleteBackNotLine, 0}},
+ {3281, {wxStyledTextCtrl, homeDisplay, 0}},
+ {3282, {wxStyledTextCtrl, homeDisplayExtend, 0}},
+ {3283, {wxStyledTextCtrl, lineEndDisplay, 0}},
+ {3284, {wxStyledTextCtrl, lineEndDisplayExtend, 0}},
+ {3285, {wxStyledTextCtrl, homeWrapExtend, 0}},
+ {3286, {wxStyledTextCtrl, lineEndWrap, 0}},
+ {3287, {wxStyledTextCtrl, lineEndWrapExtend, 0}},
+ {3288, {wxStyledTextCtrl, vCHomeWrap, 0}},
+ {3289, {wxStyledTextCtrl, vCHomeWrapExtend, 0}},
+ {3290, {wxStyledTextCtrl, lineCopy, 0}},
+ {3291, {wxStyledTextCtrl, moveCaretInsideView, 0}},
+ {3292, {wxStyledTextCtrl, lineLength, 1}},
+ {3293, {wxStyledTextCtrl, braceHighlight, 2}},
+ {3294, {wxStyledTextCtrl, braceBadLight, 1}},
+ {3295, {wxStyledTextCtrl, braceMatch, 1}},
+ {3296, {wxStyledTextCtrl, getViewEOL, 0}},
+ {3297, {wxStyledTextCtrl, setViewEOL, 1}},
+ {3298, {wxStyledTextCtrl, setModEventMask, 1}},
+ {3299, {wxStyledTextCtrl, getEdgeColumn, 0}},
+ {3300, {wxStyledTextCtrl, setEdgeColumn, 1}},
+ {3301, {wxStyledTextCtrl, setEdgeMode, 1}},
+ {3302, {wxStyledTextCtrl, getEdgeMode, 0}},
+ {3303, {wxStyledTextCtrl, getEdgeColour, 0}},
+ {3304, {wxStyledTextCtrl, setEdgeColour, 1}},
+ {3305, {wxStyledTextCtrl, searchAnchor, 0}},
+ {3306, {wxStyledTextCtrl, searchNext, 2}},
+ {3307, {wxStyledTextCtrl, searchPrev, 2}},
+ {3308, {wxStyledTextCtrl, linesOnScreen, 0}},
+ {3309, {wxStyledTextCtrl, usePopUp, 1}},
+ {3310, {wxStyledTextCtrl, selectionIsRectangle, 0}},
+ {3311, {wxStyledTextCtrl, setZoom, 1}},
+ {3312, {wxStyledTextCtrl, getZoom, 0}},
+ {3313, {wxStyledTextCtrl, getModEventMask, 0}},
+ {3314, {wxStyledTextCtrl, setSTCFocus, 1}},
+ {3315, {wxStyledTextCtrl, getSTCFocus, 0}},
+ {3316, {wxStyledTextCtrl, setStatus, 1}},
+ {3317, {wxStyledTextCtrl, getStatus, 0}},
+ {3318, {wxStyledTextCtrl, setMouseDownCaptures, 1}},
+ {3319, {wxStyledTextCtrl, getMouseDownCaptures, 0}},
+ {3320, {wxStyledTextCtrl, setSTCCursor, 1}},
+ {3321, {wxStyledTextCtrl, getSTCCursor, 0}},
+ {3322, {wxStyledTextCtrl, setControlCharSymbol, 1}},
+ {3323, {wxStyledTextCtrl, getControlCharSymbol, 0}},
+ {3324, {wxStyledTextCtrl, wordPartLeft, 0}},
+ {3325, {wxStyledTextCtrl, wordPartLeftExtend, 0}},
+ {3326, {wxStyledTextCtrl, wordPartRight, 0}},
+ {3327, {wxStyledTextCtrl, wordPartRightExtend, 0}},
+ {3328, {wxStyledTextCtrl, setVisiblePolicy, 2}},
+ {3329, {wxStyledTextCtrl, delLineLeft, 0}},
+ {3330, {wxStyledTextCtrl, delLineRight, 0}},
+ {3331, {wxStyledTextCtrl, getXOffset, 0}},
+ {3332, {wxStyledTextCtrl, chooseCaretX, 0}},
+ {3333, {wxStyledTextCtrl, setXCaretPolicy, 2}},
+ {3334, {wxStyledTextCtrl, setYCaretPolicy, 2}},
+ {3335, {wxStyledTextCtrl, getPrintWrapMode, 0}},
+ {3336, {wxStyledTextCtrl, setHotspotActiveForeground, 2}},
+ {3337, {wxStyledTextCtrl, setHotspotActiveBackground, 2}},
+ {3338, {wxStyledTextCtrl, setHotspotActiveUnderline, 1}},
+ {3339, {wxStyledTextCtrl, setHotspotSingleLine, 1}},
+ {3340, {wxStyledTextCtrl, paraDownExtend, 0}},
+ {3341, {wxStyledTextCtrl, paraUp, 0}},
+ {3342, {wxStyledTextCtrl, paraUpExtend, 0}},
+ {3343, {wxStyledTextCtrl, positionBefore, 1}},
+ {3344, {wxStyledTextCtrl, positionAfter, 1}},
+ {3345, {wxStyledTextCtrl, copyRange, 2}},
+ {3346, {wxStyledTextCtrl, copyText, 2}},
+ {3347, {wxStyledTextCtrl, setSelectionMode, 1}},
+ {3348, {wxStyledTextCtrl, getSelectionMode, 0}},
+ {3349, {wxStyledTextCtrl, lineDownRectExtend, 0}},
+ {3350, {wxStyledTextCtrl, lineUpRectExtend, 0}},
+ {3351, {wxStyledTextCtrl, charLeftRectExtend, 0}},
+ {3352, {wxStyledTextCtrl, charRightRectExtend, 0}},
+ {3353, {wxStyledTextCtrl, homeRectExtend, 0}},
+ {3354, {wxStyledTextCtrl, vCHomeRectExtend, 0}},
+ {3355, {wxStyledTextCtrl, lineEndRectExtend, 0}},
+ {3356, {wxStyledTextCtrl, pageUpRectExtend, 0}},
+ {3357, {wxStyledTextCtrl, pageDownRectExtend, 0}},
+ {3358, {wxStyledTextCtrl, stutteredPageUp, 0}},
+ {3359, {wxStyledTextCtrl, stutteredPageUpExtend, 0}},
+ {3360, {wxStyledTextCtrl, stutteredPageDown, 0}},
+ {3361, {wxStyledTextCtrl, stutteredPageDownExtend, 0}},
+ {3362, {wxStyledTextCtrl, wordLeftEnd, 0}},
+ {3363, {wxStyledTextCtrl, wordLeftEndExtend, 0}},
+ {3364, {wxStyledTextCtrl, wordRightEnd, 0}},
+ {3365, {wxStyledTextCtrl, wordRightEndExtend, 0}},
+ {3366, {wxStyledTextCtrl, setWhitespaceChars, 1}},
+ {3367, {wxStyledTextCtrl, setCharsDefault, 0}},
+ {3368, {wxStyledTextCtrl, autoCompGetCurrent, 0}},
+ {3369, {wxStyledTextCtrl, allocate, 1}},
+ {3370, {wxStyledTextCtrl, findColumn, 2}},
+ {3371, {wxStyledTextCtrl, getCaretSticky, 0}},
+ {3372, {wxStyledTextCtrl, setCaretSticky, 1}},
+ {3373, {wxStyledTextCtrl, toggleCaretSticky, 0}},
+ {3374, {wxStyledTextCtrl, setPasteConvertEndings, 1}},
+ {3375, {wxStyledTextCtrl, getPasteConvertEndings, 0}},
+ {3376, {wxStyledTextCtrl, selectionDuplicate, 0}},
+ {3377, {wxStyledTextCtrl, setCaretLineBackAlpha, 1}},
+ {3378, {wxStyledTextCtrl, getCaretLineBackAlpha, 0}},
+ {3379, {wxStyledTextCtrl, startRecord, 0}},
+ {3380, {wxStyledTextCtrl, stopRecord, 0}},
+ {3381, {wxStyledTextCtrl, setLexer, 1}},
+ {3382, {wxStyledTextCtrl, getLexer, 0}},
+ {3383, {wxStyledTextCtrl, colourise, 2}},
+ {3384, {wxStyledTextCtrl, setProperty, 2}},
+ {3385, {wxStyledTextCtrl, setKeyWords, 2}},
+ {3386, {wxStyledTextCtrl, setLexerLanguage, 1}},
+ {3387, {wxStyledTextCtrl, getProperty, 1}},
+ {3388, {wxStyledTextCtrl, getStyleBitsNeeded, 0}},
+ {3389, {wxStyledTextCtrl, getCurrentLine, 0}},
+ {3390, {wxStyledTextCtrl, styleSetSpec, 2}},
+ {3391, {wxStyledTextCtrl, styleSetFont, 2}},
+ {3392, {wxStyledTextCtrl, styleSetFontAttr, 7}},
+ {3393, {wxStyledTextCtrl, styleSetCharacterSet, 2}},
+ {3394, {wxStyledTextCtrl, styleSetFontEncoding, 2}},
+ {3395, {wxStyledTextCtrl, cmdKeyExecute, 1}},
+ {3396, {wxStyledTextCtrl, setMargins, 2}},
+ {3397, {wxStyledTextCtrl, getSelection, 2}},
+ {3398, {wxStyledTextCtrl, pointFromPosition, 1}},
+ {3399, {wxStyledTextCtrl, scrollToLine, 1}},
+ {3400, {wxStyledTextCtrl, scrollToColumn, 1}},
+ {3401, {wxStyledTextCtrl, setVScrollBar, 1}},
+ {3402, {wxStyledTextCtrl, setHScrollBar, 1}},
+ {3403, {wxStyledTextCtrl, getLastKeydownProcessed, 0}},
+ {3404, {wxStyledTextCtrl, setLastKeydownProcessed, 1}},
+ {3405, {wxStyledTextCtrl, saveFile, 1}},
+ {3406, {wxStyledTextCtrl, loadFile, 1}},
+ {3407, {wxStyledTextCtrl, doDragOver, 3}},
+ {3408, {wxStyledTextCtrl, doDropText, 3}},
+ {3409, {wxStyledTextCtrl, getUseAntiAliasing, 0}},
+ {3410, {wxStyledTextCtrl, addTextRaw, 1}},
+ {3411, {wxStyledTextCtrl, insertTextRaw, 2}},
+ {3412, {wxStyledTextCtrl, getCurLineRaw, 1}},
+ {3413, {wxStyledTextCtrl, getLineRaw, 1}},
+ {3414, {wxStyledTextCtrl, getSelectedTextRaw, 0}},
+ {3415, {wxStyledTextCtrl, getTextRangeRaw, 2}},
+ {3416, {wxStyledTextCtrl, setTextRaw, 1}},
+ {3417, {wxStyledTextCtrl, getTextRaw, 0}},
+ {3418, {wxStyledTextCtrl, appendTextRaw, 1}},
+ {3419, {wxArtProvider, getBitmap, 2}},
+ {3420, {wxArtProvider, getIcon, 2}},
+ {3421, {wxTreeEvent, getKeyCode, 0}},
+ {3422, {wxTreeEvent, getItem, 0}},
+ {3423, {wxTreeEvent, getKeyEvent, 0}},
+ {3424, {wxTreeEvent, getLabel, 0}},
+ {3425, {wxTreeEvent, getOldItem, 0}},
+ {3426, {wxTreeEvent, getPoint, 0}},
+ {3427, {wxTreeEvent, isEditCancelled, 0}},
+ {3428, {wxTreeEvent, setToolTip, 1}},
+ {3429, {wxNotebookEvent, getOldSelection, 0}},
+ {3430, {wxNotebookEvent, getSelection, 0}},
+ {3431, {wxNotebookEvent, setOldSelection, 1}},
+ {3432, {wxNotebookEvent, setSelection, 1}},
+ {3433, {wxFileDataObject, new, 0}},
+ {3434, {wxFileDataObject, addFile, 1}},
+ {3435, {wxFileDataObject, getFilenames, 0}},
+ {3436, {wxFileDataObject, 'Destroy', undefined}},
+ {3437, {wxTextDataObject, new, 1}},
+ {3438, {wxTextDataObject, getTextLength, 0}},
+ {3439, {wxTextDataObject, getText, 0}},
+ {3440, {wxTextDataObject, setText, 1}},
+ {3441, {wxTextDataObject, 'Destroy', undefined}},
+ {3442, {wxBitmapDataObject, new_1_1, 1}},
+ {3443, {wxBitmapDataObject, new_1_0, 1}},
+ {3444, {wxBitmapDataObject, getBitmap, 0}},
+ {3445, {wxBitmapDataObject, setBitmap, 1}},
+ {3446, {wxBitmapDataObject, 'Destroy', undefined}},
+ {3448, {wxClipboard, new, 0}},
+ {3449, {wxClipboard, destruct, 0}},
+ {3450, {wxClipboard, addData, 1}},
+ {3451, {wxClipboard, clear, 0}},
+ {3452, {wxClipboard, close, 0}},
+ {3453, {wxClipboard, flush, 0}},
+ {3454, {wxClipboard, getData, 1}},
+ {3455, {wxClipboard, isOpened, 0}},
+ {3456, {wxClipboard, open, 0}},
+ {3457, {wxClipboard, setData, 1}},
+ {3459, {wxClipboard, usePrimarySelection, 1}},
+ {3460, {wxClipboard, isSupported, 1}},
+ {3461, {wxClipboard, get, 0}},
+ {3462, {wxSpinEvent, getPosition, 0}},
+ {3463, {wxSpinEvent, setPosition, 1}},
+ {3464, {wxSplitterWindow, new_0, 0}},
+ {3465, {wxSplitterWindow, new_2, 2}},
+ {3466, {wxSplitterWindow, destruct, 0}},
+ {3467, {wxSplitterWindow, create, 2}},
+ {3468, {wxSplitterWindow, getMinimumPaneSize, 0}},
+ {3469, {wxSplitterWindow, getSashGravity, 0}},
+ {3470, {wxSplitterWindow, getSashPosition, 0}},
+ {3471, {wxSplitterWindow, getSplitMode, 0}},
+ {3472, {wxSplitterWindow, getWindow1, 0}},
+ {3473, {wxSplitterWindow, getWindow2, 0}},
+ {3474, {wxSplitterWindow, initialize, 1}},
+ {3475, {wxSplitterWindow, isSplit, 0}},
+ {3476, {wxSplitterWindow, replaceWindow, 2}},
+ {3477, {wxSplitterWindow, setSashGravity, 1}},
+ {3478, {wxSplitterWindow, setSashPosition, 2}},
+ {3479, {wxSplitterWindow, setSashSize, 1}},
+ {3480, {wxSplitterWindow, setMinimumPaneSize, 1}},
+ {3481, {wxSplitterWindow, setSplitMode, 1}},
+ {3482, {wxSplitterWindow, splitHorizontally, 3}},
+ {3483, {wxSplitterWindow, splitVertically, 3}},
+ {3484, {wxSplitterWindow, unsplit, 1}},
+ {3485, {wxSplitterWindow, updateSize, 0}},
+ {3486, {wxSplitterEvent, getSashPosition, 0}},
+ {3487, {wxSplitterEvent, getX, 0}},
+ {3488, {wxSplitterEvent, getY, 0}},
+ {3489, {wxSplitterEvent, getWindowBeingRemoved, 0}},
+ {3490, {wxSplitterEvent, setSashPosition, 1}},
+ {3491, {wxHtmlWindow, new_0, 0}},
+ {3492, {wxHtmlWindow, new_2, 2}},
+ {3493, {wxHtmlWindow, appendToPage, 1}},
+ {3494, {wxHtmlWindow, getOpenedAnchor, 0}},
+ {3495, {wxHtmlWindow, getOpenedPage, 0}},
+ {3496, {wxHtmlWindow, getOpenedPageTitle, 0}},
+ {3497, {wxHtmlWindow, getRelatedFrame, 0}},
+ {3498, {wxHtmlWindow, historyBack, 0}},
+ {3499, {wxHtmlWindow, historyCanBack, 0}},
+ {3500, {wxHtmlWindow, historyCanForward, 0}},
+ {3501, {wxHtmlWindow, historyClear, 0}},
+ {3502, {wxHtmlWindow, historyForward, 0}},
+ {3503, {wxHtmlWindow, loadFile, 1}},
+ {3504, {wxHtmlWindow, loadPage, 1}},
+ {3505, {wxHtmlWindow, selectAll, 0}},
+ {3506, {wxHtmlWindow, selectionToText, 0}},
+ {3507, {wxHtmlWindow, selectLine, 1}},
+ {3508, {wxHtmlWindow, selectWord, 1}},
+ {3509, {wxHtmlWindow, setBorders, 1}},
+ {3510, {wxHtmlWindow, setFonts, 3}},
+ {3511, {wxHtmlWindow, setPage, 1}},
+ {3512, {wxHtmlWindow, setRelatedFrame, 2}},
+ {3513, {wxHtmlWindow, setRelatedStatusBar, 1}},
+ {3514, {wxHtmlWindow, toText, 0}},
+ {3515, {wxHtmlWindow, 'Destroy', undefined}},
+ {3516, {wxHtmlLinkEvent, getLinkInfo, 0}},
+ {3517, {wxSystemSettings, getColour, 1}},
+ {3518, {wxSystemSettings, getFont, 1}},
+ {3519, {wxSystemSettings, getMetric, 2}},
+ {3520, {wxSystemSettings, getScreenType, 0}},
+ {3521, {wxSystemOptions, getOption, 1}},
+ {3522, {wxSystemOptions, getOptionInt, 1}},
+ {3523, {wxSystemOptions, hasOption, 1}},
+ {3524, {wxSystemOptions, isFalse, 1}},
+ {3525, {wxSystemOptions, setOption_2_1, 2}},
+ {3526, {wxSystemOptions, setOption_2_0, 2}},
+ {3527, {wxAuiNotebookEvent, setSelection, 1}},
+ {3528, {wxAuiNotebookEvent, getSelection, 0}},
+ {3529, {wxAuiNotebookEvent, setOldSelection, 1}},
+ {3530, {wxAuiNotebookEvent, getOldSelection, 0}},
+ {3531, {wxAuiNotebookEvent, setDragSource, 1}},
+ {3532, {wxAuiNotebookEvent, getDragSource, 0}},
+ {3533, {wxAuiManagerEvent, setManager, 1}},
+ {3534, {wxAuiManagerEvent, getManager, 0}},
+ {3535, {wxAuiManagerEvent, setPane, 1}},
+ {3536, {wxAuiManagerEvent, getPane, 0}},
+ {3537, {wxAuiManagerEvent, setButton, 1}},
+ {3538, {wxAuiManagerEvent, getButton, 0}},
+ {3539, {wxAuiManagerEvent, setDC, 1}},
+ {3540, {wxAuiManagerEvent, getDC, 0}},
+ {3541, {wxAuiManagerEvent, veto, 1}},
+ {3542, {wxAuiManagerEvent, getVeto, 0}},
+ {3543, {wxAuiManagerEvent, setCanVeto, 1}},
+ {3544, {wxAuiManagerEvent, canVeto, 0}},
+ {3545, {wxLogNull, new, 0}},
+ {3546, {wxLogNull, 'Destroy', undefined}},
+ {3547, {wxTaskBarIcon, new, 0}},
+ {3548, {wxTaskBarIcon, destruct, 0}},
+ {3549, {wxTaskBarIcon, popupMenu, 1}},
+ {3550, {wxTaskBarIcon, removeIcon, 0}},
+ {3551, {wxTaskBarIcon, setIcon, 2}},
+ {3552, {wxLocale, new_0, 0}},
+ {3554, {wxLocale, new_2, 2}},
+ {3555, {wxLocale, destruct, 0}},
+ {3557, {wxLocale, init, 1}},
+ {3558, {wxLocale, addCatalog_1, 1}},
+ {3559, {wxLocale, addCatalog_3, 3}},
+ {3560, {wxLocale, addCatalogLookupPathPrefix, 1}},
+ {3561, {wxLocale, getCanonicalName, 0}},
+ {3562, {wxLocale, getLanguage, 0}},
+ {3563, {wxLocale, getLanguageName, 1}},
+ {3564, {wxLocale, getLocale, 0}},
+ {3565, {wxLocale, getName, 0}},
+ {3566, {wxLocale, getString_2, 2}},
+ {3567, {wxLocale, getString_4, 4}},
+ {3568, {wxLocale, getHeaderValue, 2}},
+ {3569, {wxLocale, getSysName, 0}},
+ {3570, {wxLocale, getSystemEncoding, 0}},
+ {3571, {wxLocale, getSystemEncodingName, 0}},
+ {3572, {wxLocale, getSystemLanguage, 0}},
+ {3573, {wxLocale, isLoaded, 1}},
+ {3574, {wxLocale, isOk, 0}},
+ {3575, {wxActivateEvent, getActive, 0}},
+ {3577, {wxPopupWindow, new_2, 2}},
+ {3578, {wxPopupWindow, new_0, 0}},
+ {3580, {wxPopupWindow, destruct, 0}},
+ {3581, {wxPopupWindow, create, 2}},
+ {3582, {wxPopupWindow, position, 2}},
+ {3583, {wxPopupTransientWindow, new_0, 0}},
+ {3584, {wxPopupTransientWindow, new_2, 2}},
+ {3585, {wxPopupTransientWindow, destruct, 0}},
+ {3586, {wxPopupTransientWindow, popup, 1}},
+ {3587, {wxPopupTransientWindow, dismiss, 0}},
+ {3588, {wxOverlay, new, 0}},
+ {3589, {wxOverlay, destruct, 0}},
+ {3590, {wxOverlay, reset, 0}},
+ {3591, {wxDCOverlay, new_6, 6}},
+ {3592, {wxDCOverlay, new_2, 2}},
+ {3593, {wxDCOverlay, destruct, 0}},
+ {3594, {wxDCOverlay, clear, 0}},
{-1, {mod, func, -1}}
].
diff --git a/lib/wx/src/gen/wxe_funcs.hrl b/lib/wx/src/gen/wxe_funcs.hrl
index d8c2ba9171..35688f3869 100644
--- a/lib/wx/src/gen/wxe_funcs.hrl
+++ b/lib/wx/src/gen/wxe_funcs.hrl
@@ -860,2503 +860,2512 @@
-define(wxToolBar_AddTool_6, 981).
-define(wxToolBar_AddCheckTool, 982).
-define(wxToolBar_AddRadioTool, 983).
--define(wxToolBar_DeleteTool, 984).
--define(wxToolBar_DeleteToolByPos, 985).
--define(wxToolBar_EnableTool, 986).
--define(wxToolBar_FindById, 987).
--define(wxToolBar_FindControl, 988).
--define(wxToolBar_FindToolForPosition, 989).
--define(wxToolBar_GetToolSize, 990).
--define(wxToolBar_GetToolBitmapSize, 991).
--define(wxToolBar_GetMargins, 992).
--define(wxToolBar_GetToolEnabled, 993).
--define(wxToolBar_GetToolLongHelp, 994).
--define(wxToolBar_GetToolPacking, 995).
--define(wxToolBar_GetToolPos, 996).
--define(wxToolBar_GetToolSeparation, 997).
--define(wxToolBar_GetToolShortHelp, 998).
--define(wxToolBar_GetToolState, 999).
--define(wxToolBar_InsertControl, 1000).
--define(wxToolBar_InsertSeparator, 1001).
--define(wxToolBar_InsertTool_5, 1002).
--define(wxToolBar_InsertTool_2, 1003).
--define(wxToolBar_InsertTool_4, 1004).
--define(wxToolBar_Realize, 1005).
--define(wxToolBar_RemoveTool, 1006).
--define(wxToolBar_SetMargins, 1007).
--define(wxToolBar_SetToolBitmapSize, 1008).
--define(wxToolBar_SetToolLongHelp, 1009).
--define(wxToolBar_SetToolPacking, 1010).
--define(wxToolBar_SetToolShortHelp, 1011).
--define(wxToolBar_SetToolSeparation, 1012).
--define(wxToolBar_ToggleTool, 1013).
--define(wxStatusBar_new_0, 1015).
--define(wxStatusBar_new_2, 1016).
--define(wxStatusBar_destruct, 1018).
--define(wxStatusBar_Create, 1019).
--define(wxStatusBar_GetFieldRect, 1020).
--define(wxStatusBar_GetFieldsCount, 1021).
--define(wxStatusBar_GetStatusText, 1022).
--define(wxStatusBar_PopStatusText, 1023).
--define(wxStatusBar_PushStatusText, 1024).
--define(wxStatusBar_SetFieldsCount, 1025).
--define(wxStatusBar_SetMinHeight, 1026).
--define(wxStatusBar_SetStatusText, 1027).
--define(wxStatusBar_SetStatusWidths, 1028).
--define(wxStatusBar_SetStatusStyles, 1029).
--define(wxBitmap_new_0, 1030).
--define(wxBitmap_new_3, 1031).
--define(wxBitmap_new_4, 1032).
--define(wxBitmap_new_2_0, 1033).
--define(wxBitmap_new_2_1, 1034).
--define(wxBitmap_destruct, 1035).
--define(wxBitmap_ConvertToImage, 1036).
--define(wxBitmap_CopyFromIcon, 1037).
--define(wxBitmap_Create, 1038).
--define(wxBitmap_GetDepth, 1039).
--define(wxBitmap_GetHeight, 1040).
--define(wxBitmap_GetPalette, 1041).
--define(wxBitmap_GetMask, 1042).
--define(wxBitmap_GetWidth, 1043).
--define(wxBitmap_GetSubBitmap, 1044).
--define(wxBitmap_LoadFile, 1045).
--define(wxBitmap_Ok, 1046).
--define(wxBitmap_SaveFile, 1047).
--define(wxBitmap_SetDepth, 1048).
--define(wxBitmap_SetHeight, 1049).
--define(wxBitmap_SetMask, 1050).
--define(wxBitmap_SetPalette, 1051).
--define(wxBitmap_SetWidth, 1052).
--define(wxIcon_new_0, 1053).
--define(wxIcon_new_2, 1054).
--define(wxIcon_new_1, 1055).
--define(wxIcon_CopyFromBitmap, 1056).
--define(wxIcon_destroy, 1057).
--define(wxIconBundle_new_0, 1058).
--define(wxIconBundle_new_2, 1059).
--define(wxIconBundle_new_1_0, 1060).
--define(wxIconBundle_new_1_1, 1061).
--define(wxIconBundle_destruct, 1062).
--define(wxIconBundle_AddIcon_2, 1063).
--define(wxIconBundle_AddIcon_1, 1064).
--define(wxIconBundle_GetIcon_1_1, 1065).
--define(wxIconBundle_GetIcon_1_0, 1066).
--define(wxCursor_new_0, 1067).
--define(wxCursor_new_1_0, 1068).
--define(wxCursor_new_1_1, 1069).
--define(wxCursor_new_4, 1070).
--define(wxCursor_destruct, 1071).
--define(wxCursor_Ok, 1072).
--define(wxMask_new_0, 1073).
--define(wxMask_new_2_1, 1074).
--define(wxMask_new_2_0, 1075).
--define(wxMask_new_1, 1076).
--define(wxMask_destruct, 1077).
--define(wxMask_Create_2_1, 1078).
--define(wxMask_Create_2_0, 1079).
--define(wxMask_Create_1, 1080).
--define(wxImage_new_0, 1081).
--define(wxImage_new_3_0, 1082).
--define(wxImage_new_4, 1083).
--define(wxImage_new_5, 1084).
--define(wxImage_new_2, 1085).
--define(wxImage_new_3_1, 1086).
--define(wxImage_Blur, 1087).
--define(wxImage_BlurHorizontal, 1088).
--define(wxImage_BlurVertical, 1089).
--define(wxImage_ConvertAlphaToMask, 1090).
--define(wxImage_ConvertToGreyscale, 1091).
--define(wxImage_ConvertToMono, 1092).
--define(wxImage_Copy, 1093).
--define(wxImage_Create_3, 1094).
--define(wxImage_Create_4, 1095).
--define(wxImage_Create_5, 1096).
--define(wxImage_Destroy, 1097).
--define(wxImage_FindFirstUnusedColour, 1098).
--define(wxImage_GetImageExtWildcard, 1099).
--define(wxImage_GetAlpha_2, 1100).
--define(wxImage_GetAlpha_0, 1101).
--define(wxImage_GetBlue, 1102).
--define(wxImage_GetData, 1103).
--define(wxImage_GetGreen, 1104).
--define(wxImage_GetImageCount, 1105).
--define(wxImage_GetHeight, 1106).
--define(wxImage_GetMaskBlue, 1107).
--define(wxImage_GetMaskGreen, 1108).
--define(wxImage_GetMaskRed, 1109).
--define(wxImage_GetOrFindMaskColour, 1110).
--define(wxImage_GetPalette, 1111).
--define(wxImage_GetRed, 1112).
--define(wxImage_GetSubImage, 1113).
--define(wxImage_GetWidth, 1114).
--define(wxImage_HasAlpha, 1115).
--define(wxImage_HasMask, 1116).
--define(wxImage_GetOption, 1117).
--define(wxImage_GetOptionInt, 1118).
--define(wxImage_HasOption, 1119).
--define(wxImage_InitAlpha, 1120).
--define(wxImage_InitStandardHandlers, 1121).
--define(wxImage_IsTransparent, 1122).
--define(wxImage_LoadFile_2, 1123).
--define(wxImage_LoadFile_3, 1124).
--define(wxImage_Ok, 1125).
--define(wxImage_RemoveHandler, 1126).
--define(wxImage_Mirror, 1127).
--define(wxImage_Replace, 1128).
--define(wxImage_Rescale, 1129).
--define(wxImage_Resize, 1130).
--define(wxImage_Rotate, 1131).
--define(wxImage_RotateHue, 1132).
--define(wxImage_Rotate90, 1133).
--define(wxImage_SaveFile_1, 1134).
--define(wxImage_SaveFile_2_0, 1135).
--define(wxImage_SaveFile_2_1, 1136).
--define(wxImage_Scale, 1137).
--define(wxImage_Size, 1138).
--define(wxImage_SetAlpha_3, 1139).
--define(wxImage_SetAlpha_2, 1140).
--define(wxImage_SetData_2, 1141).
--define(wxImage_SetData_4, 1142).
--define(wxImage_SetMask, 1143).
--define(wxImage_SetMaskColour, 1144).
--define(wxImage_SetMaskFromImage, 1145).
--define(wxImage_SetOption_2_1, 1146).
--define(wxImage_SetOption_2_0, 1147).
--define(wxImage_SetPalette, 1148).
--define(wxImage_SetRGB_5, 1149).
--define(wxImage_SetRGB_4, 1150).
--define(wxImage_destroy, 1151).
--define(wxBrush_new_0, 1152).
--define(wxBrush_new_2, 1153).
--define(wxBrush_new_1, 1154).
--define(wxBrush_destruct, 1156).
--define(wxBrush_GetColour, 1157).
--define(wxBrush_GetStipple, 1158).
--define(wxBrush_GetStyle, 1159).
--define(wxBrush_IsHatch, 1160).
--define(wxBrush_IsOk, 1161).
--define(wxBrush_SetColour_1, 1162).
--define(wxBrush_SetColour_3, 1163).
--define(wxBrush_SetStipple, 1164).
--define(wxBrush_SetStyle, 1165).
--define(wxPen_new_0, 1166).
--define(wxPen_new_2, 1167).
--define(wxPen_destruct, 1168).
--define(wxPen_GetCap, 1169).
--define(wxPen_GetColour, 1170).
--define(wxPen_GetJoin, 1171).
--define(wxPen_GetStyle, 1172).
--define(wxPen_GetWidth, 1173).
--define(wxPen_IsOk, 1174).
--define(wxPen_SetCap, 1175).
--define(wxPen_SetColour_1, 1176).
--define(wxPen_SetColour_3, 1177).
--define(wxPen_SetJoin, 1178).
--define(wxPen_SetStyle, 1179).
--define(wxPen_SetWidth, 1180).
--define(wxRegion_new_0, 1181).
--define(wxRegion_new_4, 1182).
--define(wxRegion_new_2, 1183).
--define(wxRegion_new_1_1, 1184).
--define(wxRegion_new_1_0, 1186).
--define(wxRegion_destruct, 1188).
--define(wxRegion_Clear, 1189).
--define(wxRegion_Contains_2, 1190).
--define(wxRegion_Contains_1_0, 1191).
--define(wxRegion_Contains_4, 1192).
--define(wxRegion_Contains_1_1, 1193).
--define(wxRegion_ConvertToBitmap, 1194).
--define(wxRegion_GetBox, 1195).
--define(wxRegion_Intersect_4, 1196).
--define(wxRegion_Intersect_1_1, 1197).
--define(wxRegion_Intersect_1_0, 1198).
--define(wxRegion_IsEmpty, 1199).
--define(wxRegion_Subtract_4, 1200).
--define(wxRegion_Subtract_1_1, 1201).
--define(wxRegion_Subtract_1_0, 1202).
--define(wxRegion_Offset_2, 1203).
--define(wxRegion_Offset_1, 1204).
--define(wxRegion_Union_4, 1205).
--define(wxRegion_Union_1_2, 1206).
--define(wxRegion_Union_1_1, 1207).
--define(wxRegion_Union_1_0, 1208).
--define(wxRegion_Union_3, 1209).
--define(wxRegion_Xor_4, 1210).
--define(wxRegion_Xor_1_1, 1211).
--define(wxRegion_Xor_1_0, 1212).
--define(wxAcceleratorTable_new_0, 1213).
--define(wxAcceleratorTable_new_2, 1214).
--define(wxAcceleratorTable_destruct, 1215).
--define(wxAcceleratorTable_Ok, 1216).
--define(wxAcceleratorEntry_new_1_0, 1217).
--define(wxAcceleratorEntry_new_1_1, 1218).
--define(wxAcceleratorEntry_GetCommand, 1219).
--define(wxAcceleratorEntry_GetFlags, 1220).
--define(wxAcceleratorEntry_GetKeyCode, 1221).
--define(wxAcceleratorEntry_Set, 1222).
--define(wxAcceleratorEntry_destroy, 1223).
--define(wxCaret_new_3, 1228).
--define(wxCaret_new_2, 1229).
--define(wxCaret_destruct, 1231).
--define(wxCaret_Create_3, 1232).
--define(wxCaret_Create_2, 1233).
--define(wxCaret_GetBlinkTime, 1234).
--define(wxCaret_GetPosition, 1236).
--define(wxCaret_GetSize, 1238).
--define(wxCaret_GetWindow, 1239).
--define(wxCaret_Hide, 1240).
--define(wxCaret_IsOk, 1241).
--define(wxCaret_IsVisible, 1242).
--define(wxCaret_Move_2, 1243).
--define(wxCaret_Move_1, 1244).
--define(wxCaret_SetBlinkTime, 1245).
--define(wxCaret_SetSize_2, 1246).
--define(wxCaret_SetSize_1, 1247).
--define(wxCaret_Show, 1248).
--define(wxSizer_Add_2_1, 1249).
--define(wxSizer_Add_2_0, 1250).
--define(wxSizer_Add_3, 1251).
--define(wxSizer_Add_2_3, 1252).
--define(wxSizer_Add_2_2, 1253).
--define(wxSizer_AddSpacer, 1254).
--define(wxSizer_AddStretchSpacer, 1255).
--define(wxSizer_CalcMin, 1256).
--define(wxSizer_Clear, 1257).
--define(wxSizer_Detach_1_2, 1258).
--define(wxSizer_Detach_1_1, 1259).
--define(wxSizer_Detach_1_0, 1260).
--define(wxSizer_Fit, 1261).
--define(wxSizer_FitInside, 1262).
--define(wxSizer_GetChildren, 1263).
--define(wxSizer_GetItem_2_1, 1264).
--define(wxSizer_GetItem_2_0, 1265).
--define(wxSizer_GetItem_1, 1266).
--define(wxSizer_GetSize, 1267).
--define(wxSizer_GetPosition, 1268).
--define(wxSizer_GetMinSize, 1269).
--define(wxSizer_Hide_2_0, 1270).
--define(wxSizer_Hide_2_1, 1271).
--define(wxSizer_Hide_1, 1272).
--define(wxSizer_Insert_3_1, 1273).
--define(wxSizer_Insert_3_0, 1274).
--define(wxSizer_Insert_4, 1275).
--define(wxSizer_Insert_3_3, 1276).
--define(wxSizer_Insert_3_2, 1277).
--define(wxSizer_Insert_2, 1278).
--define(wxSizer_InsertSpacer, 1279).
--define(wxSizer_InsertStretchSpacer, 1280).
--define(wxSizer_IsShown_1_2, 1281).
--define(wxSizer_IsShown_1_1, 1282).
--define(wxSizer_IsShown_1_0, 1283).
--define(wxSizer_Layout, 1284).
--define(wxSizer_Prepend_2_1, 1285).
--define(wxSizer_Prepend_2_0, 1286).
--define(wxSizer_Prepend_3, 1287).
--define(wxSizer_Prepend_2_3, 1288).
--define(wxSizer_Prepend_2_2, 1289).
--define(wxSizer_Prepend_1, 1290).
--define(wxSizer_PrependSpacer, 1291).
--define(wxSizer_PrependStretchSpacer, 1292).
--define(wxSizer_RecalcSizes, 1293).
--define(wxSizer_Remove_1_1, 1294).
--define(wxSizer_Remove_1_0, 1295).
--define(wxSizer_Replace_3_1, 1296).
--define(wxSizer_Replace_3_0, 1297).
--define(wxSizer_Replace_2, 1298).
--define(wxSizer_SetDimension, 1299).
--define(wxSizer_SetMinSize_2, 1300).
--define(wxSizer_SetMinSize_1, 1301).
--define(wxSizer_SetItemMinSize_3_2, 1302).
--define(wxSizer_SetItemMinSize_2_2, 1303).
--define(wxSizer_SetItemMinSize_3_1, 1304).
--define(wxSizer_SetItemMinSize_2_1, 1305).
--define(wxSizer_SetItemMinSize_3_0, 1306).
--define(wxSizer_SetItemMinSize_2_0, 1307).
--define(wxSizer_SetSizeHints, 1308).
--define(wxSizer_SetVirtualSizeHints, 1309).
--define(wxSizer_Show_2_2, 1310).
--define(wxSizer_Show_2_1, 1311).
--define(wxSizer_Show_2_0, 1312).
--define(wxSizer_Show_1, 1313).
--define(wxSizerFlags_new, 1314).
--define(wxSizerFlags_Align, 1315).
--define(wxSizerFlags_Border_2, 1316).
--define(wxSizerFlags_Border_1, 1317).
--define(wxSizerFlags_Center, 1318).
--define(wxSizerFlags_Centre, 1319).
--define(wxSizerFlags_Expand, 1320).
--define(wxSizerFlags_Left, 1321).
--define(wxSizerFlags_Proportion, 1322).
--define(wxSizerFlags_Right, 1323).
--define(wxSizerFlags_destroy, 1324).
--define(wxSizerItem_new_5_1, 1325).
--define(wxSizerItem_new_2_1, 1326).
--define(wxSizerItem_new_5_0, 1327).
--define(wxSizerItem_new_2_0, 1328).
--define(wxSizerItem_new_6, 1329).
--define(wxSizerItem_new_3, 1330).
--define(wxSizerItem_new_0, 1331).
--define(wxSizerItem_destruct, 1332).
--define(wxSizerItem_CalcMin, 1333).
--define(wxSizerItem_DeleteWindows, 1334).
--define(wxSizerItem_DetachSizer, 1335).
--define(wxSizerItem_GetBorder, 1336).
--define(wxSizerItem_GetFlag, 1337).
--define(wxSizerItem_GetMinSize, 1338).
--define(wxSizerItem_GetPosition, 1339).
--define(wxSizerItem_GetProportion, 1340).
--define(wxSizerItem_GetRatio, 1341).
--define(wxSizerItem_GetRect, 1342).
--define(wxSizerItem_GetSize, 1343).
--define(wxSizerItem_GetSizer, 1344).
--define(wxSizerItem_GetSpacer, 1345).
--define(wxSizerItem_GetUserData, 1346).
--define(wxSizerItem_GetWindow, 1347).
--define(wxSizerItem_IsSizer, 1348).
--define(wxSizerItem_IsShown, 1349).
--define(wxSizerItem_IsSpacer, 1350).
--define(wxSizerItem_IsWindow, 1351).
--define(wxSizerItem_SetBorder, 1352).
--define(wxSizerItem_SetDimension, 1353).
--define(wxSizerItem_SetFlag, 1354).
--define(wxSizerItem_SetInitSize, 1355).
--define(wxSizerItem_SetMinSize_1, 1356).
--define(wxSizerItem_SetMinSize_2, 1357).
--define(wxSizerItem_SetProportion, 1358).
--define(wxSizerItem_SetRatio_2, 1359).
--define(wxSizerItem_SetRatio_1_1, 1360).
--define(wxSizerItem_SetRatio_1_0, 1361).
--define(wxSizerItem_SetSizer, 1362).
--define(wxSizerItem_SetSpacer_1, 1363).
--define(wxSizerItem_SetSpacer_2, 1364).
--define(wxSizerItem_SetWindow, 1365).
--define(wxSizerItem_Show, 1366).
--define(wxBoxSizer_new, 1367).
--define(wxBoxSizer_GetOrientation, 1368).
--define(wxBoxSizer_destroy, 1369).
--define(wxStaticBoxSizer_new_2, 1370).
--define(wxStaticBoxSizer_new_3, 1371).
--define(wxStaticBoxSizer_GetStaticBox, 1372).
--define(wxStaticBoxSizer_destroy, 1373).
--define(wxGridSizer_new_4, 1374).
--define(wxGridSizer_new_2, 1375).
--define(wxGridSizer_GetCols, 1376).
--define(wxGridSizer_GetHGap, 1377).
--define(wxGridSizer_GetRows, 1378).
--define(wxGridSizer_GetVGap, 1379).
--define(wxGridSizer_SetCols, 1380).
--define(wxGridSizer_SetHGap, 1381).
--define(wxGridSizer_SetRows, 1382).
--define(wxGridSizer_SetVGap, 1383).
--define(wxGridSizer_destroy, 1384).
--define(wxFlexGridSizer_new_4, 1385).
--define(wxFlexGridSizer_new_2, 1386).
--define(wxFlexGridSizer_AddGrowableCol, 1387).
--define(wxFlexGridSizer_AddGrowableRow, 1388).
--define(wxFlexGridSizer_GetFlexibleDirection, 1389).
--define(wxFlexGridSizer_GetNonFlexibleGrowMode, 1390).
--define(wxFlexGridSizer_RemoveGrowableCol, 1391).
--define(wxFlexGridSizer_RemoveGrowableRow, 1392).
--define(wxFlexGridSizer_SetFlexibleDirection, 1393).
--define(wxFlexGridSizer_SetNonFlexibleGrowMode, 1394).
--define(wxFlexGridSizer_destroy, 1395).
--define(wxGridBagSizer_new, 1396).
--define(wxGridBagSizer_Add_3_2, 1397).
--define(wxGridBagSizer_Add_3_1, 1398).
--define(wxGridBagSizer_Add_4, 1399).
--define(wxGridBagSizer_Add_1_0, 1400).
--define(wxGridBagSizer_Add_2_1, 1401).
--define(wxGridBagSizer_Add_2_0, 1402).
--define(wxGridBagSizer_Add_3_0, 1403).
--define(wxGridBagSizer_Add_1_1, 1404).
--define(wxGridBagSizer_CalcMin, 1405).
--define(wxGridBagSizer_CheckForIntersection_2, 1406).
--define(wxGridBagSizer_CheckForIntersection_3, 1407).
--define(wxGridBagSizer_FindItem_1_1, 1408).
--define(wxGridBagSizer_FindItem_1_0, 1409).
--define(wxGridBagSizer_FindItemAtPoint, 1410).
--define(wxGridBagSizer_FindItemAtPosition, 1411).
--define(wxGridBagSizer_FindItemWithData, 1412).
--define(wxGridBagSizer_GetCellSize, 1413).
--define(wxGridBagSizer_GetEmptyCellSize, 1414).
--define(wxGridBagSizer_GetItemPosition_1_2, 1415).
--define(wxGridBagSizer_GetItemPosition_1_1, 1416).
--define(wxGridBagSizer_GetItemPosition_1_0, 1417).
--define(wxGridBagSizer_GetItemSpan_1_2, 1418).
--define(wxGridBagSizer_GetItemSpan_1_1, 1419).
--define(wxGridBagSizer_GetItemSpan_1_0, 1420).
--define(wxGridBagSizer_SetEmptyCellSize, 1421).
--define(wxGridBagSizer_SetItemPosition_2_2, 1422).
--define(wxGridBagSizer_SetItemPosition_2_1, 1423).
--define(wxGridBagSizer_SetItemPosition_2_0, 1424).
--define(wxGridBagSizer_SetItemSpan_2_2, 1425).
--define(wxGridBagSizer_SetItemSpan_2_1, 1426).
--define(wxGridBagSizer_SetItemSpan_2_0, 1427).
--define(wxGridBagSizer_destroy, 1428).
--define(wxStdDialogButtonSizer_new, 1429).
--define(wxStdDialogButtonSizer_AddButton, 1430).
--define(wxStdDialogButtonSizer_Realize, 1431).
--define(wxStdDialogButtonSizer_SetAffirmativeButton, 1432).
--define(wxStdDialogButtonSizer_SetCancelButton, 1433).
--define(wxStdDialogButtonSizer_SetNegativeButton, 1434).
--define(wxStdDialogButtonSizer_destroy, 1435).
--define(wxFont_new_0, 1436).
--define(wxFont_new_1, 1437).
--define(wxFont_new_5, 1438).
--define(wxFont_destruct, 1440).
--define(wxFont_IsFixedWidth, 1441).
--define(wxFont_GetDefaultEncoding, 1442).
--define(wxFont_GetFaceName, 1443).
--define(wxFont_GetFamily, 1444).
--define(wxFont_GetNativeFontInfoDesc, 1445).
--define(wxFont_GetNativeFontInfoUserDesc, 1446).
--define(wxFont_GetPointSize, 1447).
--define(wxFont_GetStyle, 1448).
--define(wxFont_GetUnderlined, 1449).
--define(wxFont_GetWeight, 1450).
--define(wxFont_Ok, 1451).
--define(wxFont_SetDefaultEncoding, 1452).
--define(wxFont_SetFaceName, 1453).
--define(wxFont_SetFamily, 1454).
--define(wxFont_SetPointSize, 1455).
--define(wxFont_SetStyle, 1456).
--define(wxFont_SetUnderlined, 1457).
--define(wxFont_SetWeight, 1458).
--define(wxToolTip_Enable, 1459).
--define(wxToolTip_SetDelay, 1460).
--define(wxToolTip_new, 1461).
--define(wxToolTip_SetTip, 1462).
--define(wxToolTip_GetTip, 1463).
--define(wxToolTip_GetWindow, 1464).
--define(wxToolTip_destroy, 1465).
--define(wxButton_new_3, 1467).
--define(wxButton_new_0, 1468).
--define(wxButton_destruct, 1469).
--define(wxButton_Create, 1470).
--define(wxButton_GetDefaultSize, 1471).
--define(wxButton_SetDefault, 1472).
--define(wxButton_SetLabel, 1473).
--define(wxBitmapButton_new_4, 1475).
--define(wxBitmapButton_new_0, 1476).
--define(wxBitmapButton_Create, 1477).
--define(wxBitmapButton_GetBitmapDisabled, 1478).
--define(wxBitmapButton_GetBitmapFocus, 1480).
--define(wxBitmapButton_GetBitmapLabel, 1482).
--define(wxBitmapButton_GetBitmapSelected, 1484).
--define(wxBitmapButton_SetBitmapDisabled, 1486).
--define(wxBitmapButton_SetBitmapFocus, 1487).
--define(wxBitmapButton_SetBitmapLabel, 1488).
--define(wxBitmapButton_SetBitmapSelected, 1489).
--define(wxBitmapButton_destroy, 1490).
--define(wxToggleButton_new_0, 1491).
--define(wxToggleButton_new_4, 1492).
--define(wxToggleButton_Create, 1493).
--define(wxToggleButton_GetValue, 1494).
--define(wxToggleButton_SetValue, 1495).
--define(wxToggleButton_destroy, 1496).
--define(wxCalendarCtrl_new_0, 1497).
--define(wxCalendarCtrl_new_3, 1498).
--define(wxCalendarCtrl_Create, 1499).
--define(wxCalendarCtrl_destruct, 1500).
--define(wxCalendarCtrl_SetDate, 1501).
--define(wxCalendarCtrl_GetDate, 1502).
--define(wxCalendarCtrl_EnableYearChange, 1503).
--define(wxCalendarCtrl_EnableMonthChange, 1504).
--define(wxCalendarCtrl_EnableHolidayDisplay, 1505).
--define(wxCalendarCtrl_SetHeaderColours, 1506).
--define(wxCalendarCtrl_GetHeaderColourFg, 1507).
--define(wxCalendarCtrl_GetHeaderColourBg, 1508).
--define(wxCalendarCtrl_SetHighlightColours, 1509).
--define(wxCalendarCtrl_GetHighlightColourFg, 1510).
--define(wxCalendarCtrl_GetHighlightColourBg, 1511).
--define(wxCalendarCtrl_SetHolidayColours, 1512).
--define(wxCalendarCtrl_GetHolidayColourFg, 1513).
--define(wxCalendarCtrl_GetHolidayColourBg, 1514).
--define(wxCalendarCtrl_GetAttr, 1515).
--define(wxCalendarCtrl_SetAttr, 1516).
--define(wxCalendarCtrl_SetHoliday, 1517).
--define(wxCalendarCtrl_ResetAttr, 1518).
--define(wxCalendarCtrl_HitTest, 1519).
--define(wxCalendarDateAttr_new_0, 1520).
--define(wxCalendarDateAttr_new_2_1, 1521).
--define(wxCalendarDateAttr_new_2_0, 1522).
--define(wxCalendarDateAttr_SetTextColour, 1523).
--define(wxCalendarDateAttr_SetBackgroundColour, 1524).
--define(wxCalendarDateAttr_SetBorderColour, 1525).
--define(wxCalendarDateAttr_SetFont, 1526).
--define(wxCalendarDateAttr_SetBorder, 1527).
--define(wxCalendarDateAttr_SetHoliday, 1528).
--define(wxCalendarDateAttr_HasTextColour, 1529).
--define(wxCalendarDateAttr_HasBackgroundColour, 1530).
--define(wxCalendarDateAttr_HasBorderColour, 1531).
--define(wxCalendarDateAttr_HasFont, 1532).
--define(wxCalendarDateAttr_HasBorder, 1533).
--define(wxCalendarDateAttr_IsHoliday, 1534).
--define(wxCalendarDateAttr_GetTextColour, 1535).
--define(wxCalendarDateAttr_GetBackgroundColour, 1536).
--define(wxCalendarDateAttr_GetBorderColour, 1537).
--define(wxCalendarDateAttr_GetFont, 1538).
--define(wxCalendarDateAttr_GetBorder, 1539).
--define(wxCalendarDateAttr_destroy, 1540).
--define(wxCheckBox_new_4, 1542).
--define(wxCheckBox_new_0, 1543).
--define(wxCheckBox_Create, 1544).
--define(wxCheckBox_GetValue, 1545).
--define(wxCheckBox_Get3StateValue, 1546).
--define(wxCheckBox_Is3rdStateAllowedForUser, 1547).
--define(wxCheckBox_Is3State, 1548).
--define(wxCheckBox_IsChecked, 1549).
--define(wxCheckBox_SetValue, 1550).
--define(wxCheckBox_Set3StateValue, 1551).
--define(wxCheckBox_destroy, 1552).
--define(wxCheckListBox_new_0, 1553).
--define(wxCheckListBox_new_3, 1555).
--define(wxCheckListBox_Check, 1556).
--define(wxCheckListBox_IsChecked, 1557).
--define(wxCheckListBox_destroy, 1558).
--define(wxChoice_new_3, 1561).
--define(wxChoice_new_0, 1562).
--define(wxChoice_destruct, 1564).
--define(wxChoice_Create, 1566).
--define(wxChoice_Delete, 1567).
--define(wxChoice_GetColumns, 1568).
--define(wxChoice_SetColumns, 1569).
--define(wxComboBox_new_0, 1570).
--define(wxComboBox_new_3, 1572).
--define(wxComboBox_destruct, 1573).
--define(wxComboBox_Create, 1575).
--define(wxComboBox_CanCopy, 1576).
--define(wxComboBox_CanCut, 1577).
--define(wxComboBox_CanPaste, 1578).
--define(wxComboBox_CanRedo, 1579).
--define(wxComboBox_CanUndo, 1580).
--define(wxComboBox_Copy, 1581).
--define(wxComboBox_Cut, 1582).
--define(wxComboBox_GetInsertionPoint, 1583).
--define(wxComboBox_GetLastPosition, 1584).
--define(wxComboBox_GetValue, 1585).
--define(wxComboBox_Paste, 1586).
--define(wxComboBox_Redo, 1587).
--define(wxComboBox_Replace, 1588).
--define(wxComboBox_Remove, 1589).
--define(wxComboBox_SetInsertionPoint, 1590).
--define(wxComboBox_SetInsertionPointEnd, 1591).
--define(wxComboBox_SetSelection_1, 1592).
--define(wxComboBox_SetSelection_2, 1593).
--define(wxComboBox_SetValue, 1594).
--define(wxComboBox_Undo, 1595).
--define(wxGauge_new_0, 1596).
--define(wxGauge_new_4, 1597).
--define(wxGauge_Create, 1598).
--define(wxGauge_GetBezelFace, 1599).
--define(wxGauge_GetRange, 1600).
--define(wxGauge_GetShadowWidth, 1601).
--define(wxGauge_GetValue, 1602).
--define(wxGauge_IsVertical, 1603).
--define(wxGauge_SetBezelFace, 1604).
--define(wxGauge_SetRange, 1605).
--define(wxGauge_SetShadowWidth, 1606).
--define(wxGauge_SetValue, 1607).
--define(wxGauge_Pulse, 1608).
--define(wxGauge_destroy, 1609).
--define(wxGenericDirCtrl_new_0, 1610).
--define(wxGenericDirCtrl_new_2, 1611).
--define(wxGenericDirCtrl_destruct, 1612).
--define(wxGenericDirCtrl_Create, 1613).
--define(wxGenericDirCtrl_Init, 1614).
--define(wxGenericDirCtrl_CollapseTree, 1615).
--define(wxGenericDirCtrl_ExpandPath, 1616).
--define(wxGenericDirCtrl_GetDefaultPath, 1617).
--define(wxGenericDirCtrl_GetPath, 1618).
--define(wxGenericDirCtrl_GetFilePath, 1619).
--define(wxGenericDirCtrl_GetFilter, 1620).
--define(wxGenericDirCtrl_GetFilterIndex, 1621).
--define(wxGenericDirCtrl_GetRootId, 1622).
--define(wxGenericDirCtrl_GetTreeCtrl, 1623).
--define(wxGenericDirCtrl_ReCreateTree, 1624).
--define(wxGenericDirCtrl_SetDefaultPath, 1625).
--define(wxGenericDirCtrl_SetFilter, 1626).
--define(wxGenericDirCtrl_SetFilterIndex, 1627).
--define(wxGenericDirCtrl_SetPath, 1628).
--define(wxStaticBox_new_4, 1630).
--define(wxStaticBox_new_0, 1631).
--define(wxStaticBox_Create, 1632).
--define(wxStaticBox_destroy, 1633).
--define(wxStaticLine_new_2, 1635).
--define(wxStaticLine_new_0, 1636).
--define(wxStaticLine_Create, 1637).
--define(wxStaticLine_IsVertical, 1638).
--define(wxStaticLine_GetDefaultSize, 1639).
--define(wxStaticLine_destroy, 1640).
--define(wxListBox_new_3, 1643).
--define(wxListBox_new_0, 1644).
--define(wxListBox_destruct, 1646).
--define(wxListBox_Create, 1648).
--define(wxListBox_Deselect, 1649).
--define(wxListBox_GetSelections, 1650).
--define(wxListBox_InsertItems, 1651).
--define(wxListBox_IsSelected, 1652).
--define(wxListBox_Set, 1653).
--define(wxListBox_HitTest, 1654).
--define(wxListBox_SetFirstItem_1_0, 1655).
--define(wxListBox_SetFirstItem_1_1, 1656).
--define(wxListCtrl_new_0, 1657).
--define(wxListCtrl_new_2, 1658).
--define(wxListCtrl_Arrange, 1659).
--define(wxListCtrl_AssignImageList, 1660).
--define(wxListCtrl_ClearAll, 1661).
--define(wxListCtrl_Create, 1662).
--define(wxListCtrl_DeleteAllItems, 1663).
--define(wxListCtrl_DeleteColumn, 1664).
--define(wxListCtrl_DeleteItem, 1665).
--define(wxListCtrl_EditLabel, 1666).
--define(wxListCtrl_EnsureVisible, 1667).
--define(wxListCtrl_FindItem_3_0, 1668).
--define(wxListCtrl_FindItem_3_1, 1669).
--define(wxListCtrl_GetColumn, 1670).
--define(wxListCtrl_GetColumnCount, 1671).
--define(wxListCtrl_GetColumnWidth, 1672).
--define(wxListCtrl_GetCountPerPage, 1673).
--define(wxListCtrl_GetEditControl, 1674).
--define(wxListCtrl_GetImageList, 1675).
--define(wxListCtrl_GetItem, 1676).
--define(wxListCtrl_GetItemBackgroundColour, 1677).
--define(wxListCtrl_GetItemCount, 1678).
--define(wxListCtrl_GetItemData, 1679).
--define(wxListCtrl_GetItemFont, 1680).
--define(wxListCtrl_GetItemPosition, 1681).
--define(wxListCtrl_GetItemRect, 1682).
--define(wxListCtrl_GetItemSpacing, 1683).
--define(wxListCtrl_GetItemState, 1684).
--define(wxListCtrl_GetItemText, 1685).
--define(wxListCtrl_GetItemTextColour, 1686).
--define(wxListCtrl_GetNextItem, 1687).
--define(wxListCtrl_GetSelectedItemCount, 1688).
--define(wxListCtrl_GetTextColour, 1689).
--define(wxListCtrl_GetTopItem, 1690).
--define(wxListCtrl_GetViewRect, 1691).
--define(wxListCtrl_HitTest, 1692).
--define(wxListCtrl_InsertColumn_2, 1693).
--define(wxListCtrl_InsertColumn_3, 1694).
--define(wxListCtrl_InsertItem_1, 1695).
--define(wxListCtrl_InsertItem_2_1, 1696).
--define(wxListCtrl_InsertItem_2_0, 1697).
--define(wxListCtrl_InsertItem_3, 1698).
--define(wxListCtrl_RefreshItem, 1699).
--define(wxListCtrl_RefreshItems, 1700).
--define(wxListCtrl_ScrollList, 1701).
--define(wxListCtrl_SetBackgroundColour, 1702).
--define(wxListCtrl_SetColumn, 1703).
--define(wxListCtrl_SetColumnWidth, 1704).
--define(wxListCtrl_SetImageList, 1705).
--define(wxListCtrl_SetItem_1, 1706).
--define(wxListCtrl_SetItem_4, 1707).
--define(wxListCtrl_SetItemBackgroundColour, 1708).
--define(wxListCtrl_SetItemCount, 1709).
--define(wxListCtrl_SetItemData, 1710).
--define(wxListCtrl_SetItemFont, 1711).
--define(wxListCtrl_SetItemImage, 1712).
--define(wxListCtrl_SetItemColumnImage, 1713).
--define(wxListCtrl_SetItemPosition, 1714).
--define(wxListCtrl_SetItemState, 1715).
--define(wxListCtrl_SetItemText, 1716).
--define(wxListCtrl_SetItemTextColour, 1717).
--define(wxListCtrl_SetSingleStyle, 1718).
--define(wxListCtrl_SetTextColour, 1719).
--define(wxListCtrl_SetWindowStyleFlag, 1720).
--define(wxListCtrl_SortItems, 1721).
--define(wxListCtrl_destroy, 1722).
--define(wxListView_ClearColumnImage, 1723).
--define(wxListView_Focus, 1724).
--define(wxListView_GetFirstSelected, 1725).
--define(wxListView_GetFocusedItem, 1726).
--define(wxListView_GetNextSelected, 1727).
--define(wxListView_IsSelected, 1728).
--define(wxListView_Select, 1729).
--define(wxListView_SetColumnImage, 1730).
--define(wxListItem_new_0, 1731).
--define(wxListItem_new_1, 1732).
--define(wxListItem_destruct, 1733).
--define(wxListItem_Clear, 1734).
--define(wxListItem_GetAlign, 1735).
--define(wxListItem_GetBackgroundColour, 1736).
--define(wxListItem_GetColumn, 1737).
--define(wxListItem_GetFont, 1738).
--define(wxListItem_GetId, 1739).
--define(wxListItem_GetImage, 1740).
--define(wxListItem_GetMask, 1741).
--define(wxListItem_GetState, 1742).
--define(wxListItem_GetText, 1743).
--define(wxListItem_GetTextColour, 1744).
--define(wxListItem_GetWidth, 1745).
--define(wxListItem_SetAlign, 1746).
--define(wxListItem_SetBackgroundColour, 1747).
--define(wxListItem_SetColumn, 1748).
--define(wxListItem_SetFont, 1749).
--define(wxListItem_SetId, 1750).
--define(wxListItem_SetImage, 1751).
--define(wxListItem_SetMask, 1752).
--define(wxListItem_SetState, 1753).
--define(wxListItem_SetStateMask, 1754).
--define(wxListItem_SetText, 1755).
--define(wxListItem_SetTextColour, 1756).
--define(wxListItem_SetWidth, 1757).
--define(wxListItemAttr_new_0, 1758).
--define(wxListItemAttr_new_3, 1759).
--define(wxListItemAttr_GetBackgroundColour, 1760).
--define(wxListItemAttr_GetFont, 1761).
--define(wxListItemAttr_GetTextColour, 1762).
--define(wxListItemAttr_HasBackgroundColour, 1763).
--define(wxListItemAttr_HasFont, 1764).
--define(wxListItemAttr_HasTextColour, 1765).
--define(wxListItemAttr_SetBackgroundColour, 1766).
--define(wxListItemAttr_SetFont, 1767).
--define(wxListItemAttr_SetTextColour, 1768).
--define(wxListItemAttr_destroy, 1769).
--define(wxImageList_new_0, 1770).
--define(wxImageList_new_3, 1771).
--define(wxImageList_Add_1, 1772).
--define(wxImageList_Add_2_0, 1773).
--define(wxImageList_Add_2_1, 1774).
--define(wxImageList_Create, 1775).
--define(wxImageList_Draw, 1777).
--define(wxImageList_GetBitmap, 1778).
--define(wxImageList_GetIcon, 1779).
--define(wxImageList_GetImageCount, 1780).
--define(wxImageList_GetSize, 1781).
--define(wxImageList_Remove, 1782).
--define(wxImageList_RemoveAll, 1783).
--define(wxImageList_Replace_2, 1784).
--define(wxImageList_Replace_3, 1785).
--define(wxImageList_destroy, 1786).
--define(wxTextAttr_new_0, 1787).
--define(wxTextAttr_new_2, 1788).
--define(wxTextAttr_GetAlignment, 1789).
--define(wxTextAttr_GetBackgroundColour, 1790).
--define(wxTextAttr_GetFont, 1791).
--define(wxTextAttr_GetLeftIndent, 1792).
--define(wxTextAttr_GetLeftSubIndent, 1793).
--define(wxTextAttr_GetRightIndent, 1794).
--define(wxTextAttr_GetTabs, 1795).
--define(wxTextAttr_GetTextColour, 1796).
--define(wxTextAttr_HasBackgroundColour, 1797).
--define(wxTextAttr_HasFont, 1798).
--define(wxTextAttr_HasTextColour, 1799).
--define(wxTextAttr_GetFlags, 1800).
--define(wxTextAttr_IsDefault, 1801).
--define(wxTextAttr_SetAlignment, 1802).
--define(wxTextAttr_SetBackgroundColour, 1803).
--define(wxTextAttr_SetFlags, 1804).
--define(wxTextAttr_SetFont, 1805).
--define(wxTextAttr_SetLeftIndent, 1806).
--define(wxTextAttr_SetRightIndent, 1807).
--define(wxTextAttr_SetTabs, 1808).
--define(wxTextAttr_SetTextColour, 1809).
--define(wxTextAttr_destroy, 1810).
--define(wxTextCtrl_new_3, 1812).
--define(wxTextCtrl_new_0, 1813).
--define(wxTextCtrl_destruct, 1815).
--define(wxTextCtrl_AppendText, 1816).
--define(wxTextCtrl_CanCopy, 1817).
--define(wxTextCtrl_CanCut, 1818).
--define(wxTextCtrl_CanPaste, 1819).
--define(wxTextCtrl_CanRedo, 1820).
--define(wxTextCtrl_CanUndo, 1821).
--define(wxTextCtrl_Clear, 1822).
--define(wxTextCtrl_Copy, 1823).
--define(wxTextCtrl_Create, 1824).
--define(wxTextCtrl_Cut, 1825).
--define(wxTextCtrl_DiscardEdits, 1826).
--define(wxTextCtrl_ChangeValue, 1827).
--define(wxTextCtrl_EmulateKeyPress, 1828).
--define(wxTextCtrl_GetDefaultStyle, 1829).
--define(wxTextCtrl_GetInsertionPoint, 1830).
--define(wxTextCtrl_GetLastPosition, 1831).
--define(wxTextCtrl_GetLineLength, 1832).
--define(wxTextCtrl_GetLineText, 1833).
--define(wxTextCtrl_GetNumberOfLines, 1834).
--define(wxTextCtrl_GetRange, 1835).
--define(wxTextCtrl_GetSelection, 1836).
--define(wxTextCtrl_GetStringSelection, 1837).
--define(wxTextCtrl_GetStyle, 1838).
--define(wxTextCtrl_GetValue, 1839).
--define(wxTextCtrl_IsEditable, 1840).
--define(wxTextCtrl_IsModified, 1841).
--define(wxTextCtrl_IsMultiLine, 1842).
--define(wxTextCtrl_IsSingleLine, 1843).
--define(wxTextCtrl_LoadFile, 1844).
--define(wxTextCtrl_MarkDirty, 1845).
--define(wxTextCtrl_Paste, 1846).
--define(wxTextCtrl_PositionToXY, 1847).
--define(wxTextCtrl_Redo, 1848).
--define(wxTextCtrl_Remove, 1849).
--define(wxTextCtrl_Replace, 1850).
--define(wxTextCtrl_SaveFile, 1851).
--define(wxTextCtrl_SetDefaultStyle, 1852).
--define(wxTextCtrl_SetEditable, 1853).
--define(wxTextCtrl_SetInsertionPoint, 1854).
--define(wxTextCtrl_SetInsertionPointEnd, 1855).
--define(wxTextCtrl_SetMaxLength, 1857).
--define(wxTextCtrl_SetSelection, 1858).
--define(wxTextCtrl_SetStyle, 1859).
--define(wxTextCtrl_SetValue, 1860).
--define(wxTextCtrl_ShowPosition, 1861).
--define(wxTextCtrl_Undo, 1862).
--define(wxTextCtrl_WriteText, 1863).
--define(wxTextCtrl_XYToPosition, 1864).
--define(wxNotebook_new_0, 1867).
--define(wxNotebook_new_3, 1868).
--define(wxNotebook_destruct, 1869).
--define(wxNotebook_AddPage, 1870).
--define(wxNotebook_AdvanceSelection, 1871).
--define(wxNotebook_AssignImageList, 1872).
--define(wxNotebook_Create, 1873).
--define(wxNotebook_DeleteAllPages, 1874).
--define(wxNotebook_DeletePage, 1875).
--define(wxNotebook_RemovePage, 1876).
--define(wxNotebook_GetCurrentPage, 1877).
--define(wxNotebook_GetImageList, 1878).
--define(wxNotebook_GetPage, 1880).
--define(wxNotebook_GetPageCount, 1881).
--define(wxNotebook_GetPageImage, 1882).
--define(wxNotebook_GetPageText, 1883).
--define(wxNotebook_GetRowCount, 1884).
--define(wxNotebook_GetSelection, 1885).
--define(wxNotebook_GetThemeBackgroundColour, 1886).
--define(wxNotebook_HitTest, 1888).
--define(wxNotebook_InsertPage, 1890).
--define(wxNotebook_SetImageList, 1891).
--define(wxNotebook_SetPadding, 1892).
--define(wxNotebook_SetPageSize, 1893).
--define(wxNotebook_SetPageImage, 1894).
--define(wxNotebook_SetPageText, 1895).
--define(wxNotebook_SetSelection, 1896).
--define(wxNotebook_ChangeSelection, 1897).
--define(wxChoicebook_new_0, 1898).
--define(wxChoicebook_new_3, 1899).
--define(wxChoicebook_AddPage, 1900).
--define(wxChoicebook_AdvanceSelection, 1901).
--define(wxChoicebook_AssignImageList, 1902).
--define(wxChoicebook_Create, 1903).
--define(wxChoicebook_DeleteAllPages, 1904).
--define(wxChoicebook_DeletePage, 1905).
--define(wxChoicebook_RemovePage, 1906).
--define(wxChoicebook_GetCurrentPage, 1907).
--define(wxChoicebook_GetImageList, 1908).
--define(wxChoicebook_GetPage, 1910).
--define(wxChoicebook_GetPageCount, 1911).
--define(wxChoicebook_GetPageImage, 1912).
--define(wxChoicebook_GetPageText, 1913).
--define(wxChoicebook_GetSelection, 1914).
--define(wxChoicebook_HitTest, 1915).
--define(wxChoicebook_InsertPage, 1916).
--define(wxChoicebook_SetImageList, 1917).
--define(wxChoicebook_SetPageSize, 1918).
--define(wxChoicebook_SetPageImage, 1919).
--define(wxChoicebook_SetPageText, 1920).
--define(wxChoicebook_SetSelection, 1921).
--define(wxChoicebook_ChangeSelection, 1922).
--define(wxChoicebook_destroy, 1923).
--define(wxToolbook_new_0, 1924).
--define(wxToolbook_new_3, 1925).
--define(wxToolbook_AddPage, 1926).
--define(wxToolbook_AdvanceSelection, 1927).
--define(wxToolbook_AssignImageList, 1928).
--define(wxToolbook_Create, 1929).
--define(wxToolbook_DeleteAllPages, 1930).
--define(wxToolbook_DeletePage, 1931).
--define(wxToolbook_RemovePage, 1932).
--define(wxToolbook_GetCurrentPage, 1933).
--define(wxToolbook_GetImageList, 1934).
--define(wxToolbook_GetPage, 1936).
--define(wxToolbook_GetPageCount, 1937).
--define(wxToolbook_GetPageImage, 1938).
--define(wxToolbook_GetPageText, 1939).
--define(wxToolbook_GetSelection, 1940).
--define(wxToolbook_HitTest, 1942).
--define(wxToolbook_InsertPage, 1943).
--define(wxToolbook_SetImageList, 1944).
--define(wxToolbook_SetPageSize, 1945).
--define(wxToolbook_SetPageImage, 1946).
--define(wxToolbook_SetPageText, 1947).
--define(wxToolbook_SetSelection, 1948).
--define(wxToolbook_ChangeSelection, 1949).
--define(wxToolbook_destroy, 1950).
--define(wxListbook_new_0, 1951).
--define(wxListbook_new_3, 1952).
--define(wxListbook_AddPage, 1953).
--define(wxListbook_AdvanceSelection, 1954).
--define(wxListbook_AssignImageList, 1955).
--define(wxListbook_Create, 1956).
--define(wxListbook_DeleteAllPages, 1957).
--define(wxListbook_DeletePage, 1958).
--define(wxListbook_RemovePage, 1959).
--define(wxListbook_GetCurrentPage, 1960).
--define(wxListbook_GetImageList, 1961).
--define(wxListbook_GetPage, 1963).
--define(wxListbook_GetPageCount, 1964).
--define(wxListbook_GetPageImage, 1965).
--define(wxListbook_GetPageText, 1966).
--define(wxListbook_GetSelection, 1967).
--define(wxListbook_HitTest, 1969).
--define(wxListbook_InsertPage, 1970).
--define(wxListbook_SetImageList, 1971).
--define(wxListbook_SetPageSize, 1972).
--define(wxListbook_SetPageImage, 1973).
--define(wxListbook_SetPageText, 1974).
--define(wxListbook_SetSelection, 1975).
--define(wxListbook_ChangeSelection, 1976).
--define(wxListbook_destroy, 1977).
--define(wxTreebook_new_0, 1978).
--define(wxTreebook_new_3, 1979).
--define(wxTreebook_AddPage, 1980).
--define(wxTreebook_AdvanceSelection, 1981).
--define(wxTreebook_AssignImageList, 1982).
--define(wxTreebook_Create, 1983).
--define(wxTreebook_DeleteAllPages, 1984).
--define(wxTreebook_DeletePage, 1985).
--define(wxTreebook_RemovePage, 1986).
--define(wxTreebook_GetCurrentPage, 1987).
--define(wxTreebook_GetImageList, 1988).
--define(wxTreebook_GetPage, 1990).
--define(wxTreebook_GetPageCount, 1991).
--define(wxTreebook_GetPageImage, 1992).
--define(wxTreebook_GetPageText, 1993).
--define(wxTreebook_GetSelection, 1994).
--define(wxTreebook_ExpandNode, 1995).
--define(wxTreebook_IsNodeExpanded, 1996).
--define(wxTreebook_HitTest, 1998).
--define(wxTreebook_InsertPage, 1999).
--define(wxTreebook_InsertSubPage, 2000).
--define(wxTreebook_SetImageList, 2001).
--define(wxTreebook_SetPageSize, 2002).
--define(wxTreebook_SetPageImage, 2003).
--define(wxTreebook_SetPageText, 2004).
--define(wxTreebook_SetSelection, 2005).
--define(wxTreebook_ChangeSelection, 2006).
--define(wxTreebook_destroy, 2007).
--define(wxTreeCtrl_new_2, 2010).
--define(wxTreeCtrl_new_0, 2011).
--define(wxTreeCtrl_destruct, 2013).
--define(wxTreeCtrl_AddRoot, 2014).
--define(wxTreeCtrl_AppendItem, 2015).
--define(wxTreeCtrl_AssignImageList, 2016).
--define(wxTreeCtrl_AssignStateImageList, 2017).
--define(wxTreeCtrl_Collapse, 2018).
--define(wxTreeCtrl_CollapseAndReset, 2019).
--define(wxTreeCtrl_Create, 2020).
--define(wxTreeCtrl_Delete, 2021).
--define(wxTreeCtrl_DeleteAllItems, 2022).
--define(wxTreeCtrl_DeleteChildren, 2023).
--define(wxTreeCtrl_EditLabel, 2024).
--define(wxTreeCtrl_EnsureVisible, 2025).
--define(wxTreeCtrl_Expand, 2026).
--define(wxTreeCtrl_GetBoundingRect, 2027).
--define(wxTreeCtrl_GetChildrenCount, 2029).
--define(wxTreeCtrl_GetCount, 2030).
--define(wxTreeCtrl_GetEditControl, 2031).
--define(wxTreeCtrl_GetFirstChild, 2032).
--define(wxTreeCtrl_GetNextChild, 2033).
--define(wxTreeCtrl_GetFirstVisibleItem, 2034).
--define(wxTreeCtrl_GetImageList, 2035).
--define(wxTreeCtrl_GetIndent, 2036).
--define(wxTreeCtrl_GetItemBackgroundColour, 2037).
--define(wxTreeCtrl_GetItemData, 2038).
--define(wxTreeCtrl_GetItemFont, 2039).
--define(wxTreeCtrl_GetItemImage_1, 2040).
--define(wxTreeCtrl_GetItemImage_2, 2041).
--define(wxTreeCtrl_GetItemText, 2042).
--define(wxTreeCtrl_GetItemTextColour, 2043).
--define(wxTreeCtrl_GetLastChild, 2044).
--define(wxTreeCtrl_GetNextSibling, 2045).
--define(wxTreeCtrl_GetNextVisible, 2046).
--define(wxTreeCtrl_GetItemParent, 2047).
--define(wxTreeCtrl_GetPrevSibling, 2048).
--define(wxTreeCtrl_GetPrevVisible, 2049).
--define(wxTreeCtrl_GetRootItem, 2050).
--define(wxTreeCtrl_GetSelection, 2051).
--define(wxTreeCtrl_GetSelections, 2052).
--define(wxTreeCtrl_GetStateImageList, 2053).
--define(wxTreeCtrl_HitTest, 2054).
--define(wxTreeCtrl_InsertItem, 2056).
--define(wxTreeCtrl_IsBold, 2057).
--define(wxTreeCtrl_IsExpanded, 2058).
--define(wxTreeCtrl_IsSelected, 2059).
--define(wxTreeCtrl_IsVisible, 2060).
--define(wxTreeCtrl_ItemHasChildren, 2061).
--define(wxTreeCtrl_IsTreeItemIdOk, 2062).
--define(wxTreeCtrl_PrependItem, 2063).
--define(wxTreeCtrl_ScrollTo, 2064).
--define(wxTreeCtrl_SelectItem_1, 2065).
--define(wxTreeCtrl_SelectItem_2, 2066).
--define(wxTreeCtrl_SetIndent, 2067).
--define(wxTreeCtrl_SetImageList, 2068).
--define(wxTreeCtrl_SetItemBackgroundColour, 2069).
--define(wxTreeCtrl_SetItemBold, 2070).
--define(wxTreeCtrl_SetItemData, 2071).
--define(wxTreeCtrl_SetItemDropHighlight, 2072).
--define(wxTreeCtrl_SetItemFont, 2073).
--define(wxTreeCtrl_SetItemHasChildren, 2074).
--define(wxTreeCtrl_SetItemImage_2, 2075).
--define(wxTreeCtrl_SetItemImage_3, 2076).
--define(wxTreeCtrl_SetItemText, 2077).
--define(wxTreeCtrl_SetItemTextColour, 2078).
--define(wxTreeCtrl_SetStateImageList, 2079).
--define(wxTreeCtrl_SetWindowStyle, 2080).
--define(wxTreeCtrl_SortChildren, 2081).
--define(wxTreeCtrl_Toggle, 2082).
--define(wxTreeCtrl_ToggleItemSelection, 2083).
--define(wxTreeCtrl_Unselect, 2084).
--define(wxTreeCtrl_UnselectAll, 2085).
--define(wxTreeCtrl_UnselectItem, 2086).
--define(wxScrollBar_new_0, 2087).
--define(wxScrollBar_new_3, 2088).
--define(wxScrollBar_destruct, 2089).
--define(wxScrollBar_Create, 2090).
--define(wxScrollBar_GetRange, 2091).
--define(wxScrollBar_GetPageSize, 2092).
--define(wxScrollBar_GetThumbPosition, 2093).
--define(wxScrollBar_GetThumbSize, 2094).
--define(wxScrollBar_SetThumbPosition, 2095).
--define(wxScrollBar_SetScrollbar, 2096).
--define(wxSpinButton_new_2, 2098).
--define(wxSpinButton_new_0, 2099).
--define(wxSpinButton_Create, 2100).
--define(wxSpinButton_GetMax, 2101).
--define(wxSpinButton_GetMin, 2102).
--define(wxSpinButton_GetValue, 2103).
--define(wxSpinButton_SetRange, 2104).
--define(wxSpinButton_SetValue, 2105).
--define(wxSpinButton_destroy, 2106).
--define(wxSpinCtrl_new_0, 2107).
--define(wxSpinCtrl_new_2, 2108).
--define(wxSpinCtrl_Create, 2110).
--define(wxSpinCtrl_SetValue_1_1, 2113).
--define(wxSpinCtrl_SetValue_1_0, 2114).
--define(wxSpinCtrl_GetValue, 2116).
--define(wxSpinCtrl_SetRange, 2118).
--define(wxSpinCtrl_SetSelection, 2119).
--define(wxSpinCtrl_GetMin, 2121).
--define(wxSpinCtrl_GetMax, 2123).
--define(wxSpinCtrl_destroy, 2124).
--define(wxStaticText_new_0, 2125).
--define(wxStaticText_new_4, 2126).
--define(wxStaticText_Create, 2127).
--define(wxStaticText_GetLabel, 2128).
--define(wxStaticText_SetLabel, 2129).
--define(wxStaticText_Wrap, 2130).
--define(wxStaticText_destroy, 2131).
--define(wxStaticBitmap_new_0, 2132).
--define(wxStaticBitmap_new_4, 2133).
--define(wxStaticBitmap_Create, 2134).
--define(wxStaticBitmap_GetBitmap, 2135).
--define(wxStaticBitmap_SetBitmap, 2136).
--define(wxStaticBitmap_destroy, 2137).
--define(wxRadioBox_new, 2138).
--define(wxRadioBox_destruct, 2140).
--define(wxRadioBox_Create, 2141).
--define(wxRadioBox_Enable_2, 2142).
--define(wxRadioBox_Enable_1, 2143).
--define(wxRadioBox_GetSelection, 2144).
--define(wxRadioBox_GetString, 2145).
--define(wxRadioBox_SetSelection, 2146).
--define(wxRadioBox_Show_2, 2147).
--define(wxRadioBox_Show_1, 2148).
--define(wxRadioBox_GetColumnCount, 2149).
--define(wxRadioBox_GetItemHelpText, 2150).
--define(wxRadioBox_GetItemToolTip, 2151).
--define(wxRadioBox_GetItemFromPoint, 2153).
--define(wxRadioBox_GetRowCount, 2154).
--define(wxRadioBox_IsItemEnabled, 2155).
--define(wxRadioBox_IsItemShown, 2156).
--define(wxRadioBox_SetItemHelpText, 2157).
--define(wxRadioBox_SetItemToolTip, 2158).
--define(wxRadioButton_new_0, 2159).
--define(wxRadioButton_new_4, 2160).
--define(wxRadioButton_Create, 2161).
--define(wxRadioButton_GetValue, 2162).
--define(wxRadioButton_SetValue, 2163).
--define(wxRadioButton_destroy, 2164).
--define(wxSlider_new_6, 2166).
--define(wxSlider_new_0, 2167).
--define(wxSlider_Create, 2168).
--define(wxSlider_GetLineSize, 2169).
--define(wxSlider_GetMax, 2170).
--define(wxSlider_GetMin, 2171).
--define(wxSlider_GetPageSize, 2172).
--define(wxSlider_GetThumbLength, 2173).
--define(wxSlider_GetValue, 2174).
--define(wxSlider_SetLineSize, 2175).
--define(wxSlider_SetPageSize, 2176).
--define(wxSlider_SetRange, 2177).
--define(wxSlider_SetThumbLength, 2178).
--define(wxSlider_SetValue, 2179).
--define(wxSlider_destroy, 2180).
--define(wxDialog_new_4, 2182).
--define(wxDialog_new_0, 2183).
--define(wxDialog_destruct, 2185).
--define(wxDialog_Create, 2186).
--define(wxDialog_CreateButtonSizer, 2187).
--define(wxDialog_CreateStdDialogButtonSizer, 2188).
--define(wxDialog_EndModal, 2189).
--define(wxDialog_GetAffirmativeId, 2190).
--define(wxDialog_GetReturnCode, 2191).
--define(wxDialog_IsModal, 2192).
--define(wxDialog_SetAffirmativeId, 2193).
--define(wxDialog_SetReturnCode, 2194).
--define(wxDialog_Show, 2195).
--define(wxDialog_ShowModal, 2196).
--define(wxColourDialog_new_0, 2197).
--define(wxColourDialog_new_2, 2198).
--define(wxColourDialog_destruct, 2199).
--define(wxColourDialog_Create, 2200).
--define(wxColourDialog_GetColourData, 2201).
--define(wxColourData_new_0, 2202).
--define(wxColourData_new_1, 2203).
--define(wxColourData_destruct, 2204).
--define(wxColourData_GetChooseFull, 2205).
--define(wxColourData_GetColour, 2206).
--define(wxColourData_GetCustomColour, 2208).
--define(wxColourData_SetChooseFull, 2209).
--define(wxColourData_SetColour, 2210).
--define(wxColourData_SetCustomColour, 2211).
--define(wxPalette_new_0, 2212).
--define(wxPalette_new_4, 2213).
--define(wxPalette_destruct, 2215).
--define(wxPalette_Create, 2216).
--define(wxPalette_GetColoursCount, 2217).
--define(wxPalette_GetPixel, 2218).
--define(wxPalette_GetRGB, 2219).
--define(wxPalette_IsOk, 2220).
--define(wxDirDialog_new, 2224).
--define(wxDirDialog_destruct, 2225).
--define(wxDirDialog_GetPath, 2226).
--define(wxDirDialog_GetMessage, 2227).
--define(wxDirDialog_SetMessage, 2228).
--define(wxDirDialog_SetPath, 2229).
--define(wxFileDialog_new, 2233).
--define(wxFileDialog_destruct, 2234).
--define(wxFileDialog_GetDirectory, 2235).
--define(wxFileDialog_GetFilename, 2236).
--define(wxFileDialog_GetFilenames, 2237).
--define(wxFileDialog_GetFilterIndex, 2238).
--define(wxFileDialog_GetMessage, 2239).
--define(wxFileDialog_GetPath, 2240).
--define(wxFileDialog_GetPaths, 2241).
--define(wxFileDialog_GetWildcard, 2242).
--define(wxFileDialog_SetDirectory, 2243).
--define(wxFileDialog_SetFilename, 2244).
--define(wxFileDialog_SetFilterIndex, 2245).
--define(wxFileDialog_SetMessage, 2246).
--define(wxFileDialog_SetPath, 2247).
--define(wxFileDialog_SetWildcard, 2248).
--define(wxPickerBase_SetInternalMargin, 2249).
--define(wxPickerBase_GetInternalMargin, 2250).
--define(wxPickerBase_SetTextCtrlProportion, 2251).
--define(wxPickerBase_SetPickerCtrlProportion, 2252).
--define(wxPickerBase_GetTextCtrlProportion, 2253).
--define(wxPickerBase_GetPickerCtrlProportion, 2254).
--define(wxPickerBase_HasTextCtrl, 2255).
--define(wxPickerBase_GetTextCtrl, 2256).
--define(wxPickerBase_IsTextCtrlGrowable, 2257).
--define(wxPickerBase_SetPickerCtrlGrowable, 2258).
--define(wxPickerBase_SetTextCtrlGrowable, 2259).
--define(wxPickerBase_IsPickerCtrlGrowable, 2260).
--define(wxFilePickerCtrl_new_0, 2261).
--define(wxFilePickerCtrl_new_3, 2262).
--define(wxFilePickerCtrl_Create, 2263).
--define(wxFilePickerCtrl_GetPath, 2264).
--define(wxFilePickerCtrl_SetPath, 2265).
--define(wxFilePickerCtrl_destroy, 2266).
--define(wxDirPickerCtrl_new_0, 2267).
--define(wxDirPickerCtrl_new_3, 2268).
--define(wxDirPickerCtrl_Create, 2269).
--define(wxDirPickerCtrl_GetPath, 2270).
--define(wxDirPickerCtrl_SetPath, 2271).
--define(wxDirPickerCtrl_destroy, 2272).
--define(wxColourPickerCtrl_new_0, 2273).
--define(wxColourPickerCtrl_new_3, 2274).
--define(wxColourPickerCtrl_Create, 2275).
--define(wxColourPickerCtrl_GetColour, 2276).
--define(wxColourPickerCtrl_SetColour_1_1, 2277).
--define(wxColourPickerCtrl_SetColour_1_0, 2278).
--define(wxColourPickerCtrl_destroy, 2279).
--define(wxDatePickerCtrl_new_0, 2280).
--define(wxDatePickerCtrl_new_3, 2281).
--define(wxDatePickerCtrl_GetRange, 2282).
--define(wxDatePickerCtrl_GetValue, 2283).
--define(wxDatePickerCtrl_SetRange, 2284).
--define(wxDatePickerCtrl_SetValue, 2285).
--define(wxDatePickerCtrl_destroy, 2286).
--define(wxFontPickerCtrl_new_0, 2287).
--define(wxFontPickerCtrl_new_3, 2288).
--define(wxFontPickerCtrl_Create, 2289).
--define(wxFontPickerCtrl_GetSelectedFont, 2290).
--define(wxFontPickerCtrl_SetSelectedFont, 2291).
--define(wxFontPickerCtrl_GetMaxPointSize, 2292).
--define(wxFontPickerCtrl_SetMaxPointSize, 2293).
--define(wxFontPickerCtrl_destroy, 2294).
--define(wxFindReplaceDialog_new_0, 2297).
--define(wxFindReplaceDialog_new_4, 2298).
--define(wxFindReplaceDialog_destruct, 2299).
--define(wxFindReplaceDialog_Create, 2300).
--define(wxFindReplaceDialog_GetData, 2301).
--define(wxFindReplaceData_new_0, 2302).
--define(wxFindReplaceData_new_1, 2303).
--define(wxFindReplaceData_GetFindString, 2304).
--define(wxFindReplaceData_GetReplaceString, 2305).
--define(wxFindReplaceData_GetFlags, 2306).
--define(wxFindReplaceData_SetFlags, 2307).
--define(wxFindReplaceData_SetFindString, 2308).
--define(wxFindReplaceData_SetReplaceString, 2309).
--define(wxFindReplaceData_destroy, 2310).
--define(wxMultiChoiceDialog_new_0, 2311).
--define(wxMultiChoiceDialog_new_5, 2313).
--define(wxMultiChoiceDialog_GetSelections, 2314).
--define(wxMultiChoiceDialog_SetSelections, 2315).
--define(wxMultiChoiceDialog_destroy, 2316).
--define(wxSingleChoiceDialog_new_0, 2317).
--define(wxSingleChoiceDialog_new_5, 2319).
--define(wxSingleChoiceDialog_GetSelection, 2320).
--define(wxSingleChoiceDialog_GetStringSelection, 2321).
--define(wxSingleChoiceDialog_SetSelection, 2322).
--define(wxSingleChoiceDialog_destroy, 2323).
--define(wxTextEntryDialog_new, 2324).
--define(wxTextEntryDialog_GetValue, 2325).
--define(wxTextEntryDialog_SetValue, 2326).
--define(wxTextEntryDialog_destroy, 2327).
--define(wxPasswordEntryDialog_new, 2328).
--define(wxPasswordEntryDialog_destroy, 2329).
--define(wxFontData_new_0, 2330).
--define(wxFontData_new_1, 2331).
--define(wxFontData_destruct, 2332).
--define(wxFontData_EnableEffects, 2333).
--define(wxFontData_GetAllowSymbols, 2334).
--define(wxFontData_GetColour, 2335).
--define(wxFontData_GetChosenFont, 2336).
--define(wxFontData_GetEnableEffects, 2337).
--define(wxFontData_GetInitialFont, 2338).
--define(wxFontData_GetShowHelp, 2339).
--define(wxFontData_SetAllowSymbols, 2340).
--define(wxFontData_SetChosenFont, 2341).
--define(wxFontData_SetColour, 2342).
--define(wxFontData_SetInitialFont, 2343).
--define(wxFontData_SetRange, 2344).
--define(wxFontData_SetShowHelp, 2345).
--define(wxFontDialog_new_0, 2349).
--define(wxFontDialog_new_2, 2351).
--define(wxFontDialog_Create, 2353).
--define(wxFontDialog_GetFontData, 2354).
--define(wxFontDialog_destroy, 2356).
--define(wxProgressDialog_new, 2357).
--define(wxProgressDialog_destruct, 2358).
--define(wxProgressDialog_Resume, 2359).
--define(wxProgressDialog_Update_2, 2360).
--define(wxProgressDialog_Update_0, 2361).
--define(wxMessageDialog_new, 2362).
--define(wxMessageDialog_destruct, 2363).
--define(wxPageSetupDialog_new, 2364).
--define(wxPageSetupDialog_destruct, 2365).
--define(wxPageSetupDialog_GetPageSetupData, 2366).
--define(wxPageSetupDialog_ShowModal, 2367).
--define(wxPageSetupDialogData_new_0, 2368).
--define(wxPageSetupDialogData_new_1_0, 2369).
--define(wxPageSetupDialogData_new_1_1, 2370).
--define(wxPageSetupDialogData_destruct, 2371).
--define(wxPageSetupDialogData_EnableHelp, 2372).
--define(wxPageSetupDialogData_EnableMargins, 2373).
--define(wxPageSetupDialogData_EnableOrientation, 2374).
--define(wxPageSetupDialogData_EnablePaper, 2375).
--define(wxPageSetupDialogData_EnablePrinter, 2376).
--define(wxPageSetupDialogData_GetDefaultMinMargins, 2377).
--define(wxPageSetupDialogData_GetEnableMargins, 2378).
--define(wxPageSetupDialogData_GetEnableOrientation, 2379).
--define(wxPageSetupDialogData_GetEnablePaper, 2380).
--define(wxPageSetupDialogData_GetEnablePrinter, 2381).
--define(wxPageSetupDialogData_GetEnableHelp, 2382).
--define(wxPageSetupDialogData_GetDefaultInfo, 2383).
--define(wxPageSetupDialogData_GetMarginTopLeft, 2384).
--define(wxPageSetupDialogData_GetMarginBottomRight, 2385).
--define(wxPageSetupDialogData_GetMinMarginTopLeft, 2386).
--define(wxPageSetupDialogData_GetMinMarginBottomRight, 2387).
--define(wxPageSetupDialogData_GetPaperId, 2388).
--define(wxPageSetupDialogData_GetPaperSize, 2389).
--define(wxPageSetupDialogData_GetPrintData, 2391).
--define(wxPageSetupDialogData_IsOk, 2392).
--define(wxPageSetupDialogData_SetDefaultInfo, 2393).
--define(wxPageSetupDialogData_SetDefaultMinMargins, 2394).
--define(wxPageSetupDialogData_SetMarginTopLeft, 2395).
--define(wxPageSetupDialogData_SetMarginBottomRight, 2396).
--define(wxPageSetupDialogData_SetMinMarginTopLeft, 2397).
--define(wxPageSetupDialogData_SetMinMarginBottomRight, 2398).
--define(wxPageSetupDialogData_SetPaperId, 2399).
--define(wxPageSetupDialogData_SetPaperSize_1_1, 2400).
--define(wxPageSetupDialogData_SetPaperSize_1_0, 2401).
--define(wxPageSetupDialogData_SetPrintData, 2402).
--define(wxPrintDialog_new_2_0, 2403).
--define(wxPrintDialog_new_2_1, 2404).
--define(wxPrintDialog_destruct, 2405).
--define(wxPrintDialog_GetPrintDialogData, 2406).
--define(wxPrintDialog_GetPrintDC, 2407).
--define(wxPrintDialogData_new_0, 2408).
--define(wxPrintDialogData_new_1_1, 2409).
--define(wxPrintDialogData_new_1_0, 2410).
--define(wxPrintDialogData_destruct, 2411).
--define(wxPrintDialogData_EnableHelp, 2412).
--define(wxPrintDialogData_EnablePageNumbers, 2413).
--define(wxPrintDialogData_EnablePrintToFile, 2414).
--define(wxPrintDialogData_EnableSelection, 2415).
--define(wxPrintDialogData_GetAllPages, 2416).
--define(wxPrintDialogData_GetCollate, 2417).
--define(wxPrintDialogData_GetFromPage, 2418).
--define(wxPrintDialogData_GetMaxPage, 2419).
--define(wxPrintDialogData_GetMinPage, 2420).
--define(wxPrintDialogData_GetNoCopies, 2421).
--define(wxPrintDialogData_GetPrintData, 2422).
--define(wxPrintDialogData_GetPrintToFile, 2423).
--define(wxPrintDialogData_GetSelection, 2424).
--define(wxPrintDialogData_GetToPage, 2425).
--define(wxPrintDialogData_IsOk, 2426).
--define(wxPrintDialogData_SetCollate, 2427).
--define(wxPrintDialogData_SetFromPage, 2428).
--define(wxPrintDialogData_SetMaxPage, 2429).
--define(wxPrintDialogData_SetMinPage, 2430).
--define(wxPrintDialogData_SetNoCopies, 2431).
--define(wxPrintDialogData_SetPrintData, 2432).
--define(wxPrintDialogData_SetPrintToFile, 2433).
--define(wxPrintDialogData_SetSelection, 2434).
--define(wxPrintDialogData_SetToPage, 2435).
--define(wxPrintData_new_0, 2436).
--define(wxPrintData_new_1, 2437).
--define(wxPrintData_destruct, 2438).
--define(wxPrintData_GetCollate, 2439).
--define(wxPrintData_GetBin, 2440).
--define(wxPrintData_GetColour, 2441).
--define(wxPrintData_GetDuplex, 2442).
--define(wxPrintData_GetNoCopies, 2443).
--define(wxPrintData_GetOrientation, 2444).
--define(wxPrintData_GetPaperId, 2445).
--define(wxPrintData_GetPrinterName, 2446).
--define(wxPrintData_GetQuality, 2447).
--define(wxPrintData_IsOk, 2448).
--define(wxPrintData_SetBin, 2449).
--define(wxPrintData_SetCollate, 2450).
--define(wxPrintData_SetColour, 2451).
--define(wxPrintData_SetDuplex, 2452).
--define(wxPrintData_SetNoCopies, 2453).
--define(wxPrintData_SetOrientation, 2454).
--define(wxPrintData_SetPaperId, 2455).
--define(wxPrintData_SetPrinterName, 2456).
--define(wxPrintData_SetQuality, 2457).
--define(wxPrintPreview_new_2, 2460).
--define(wxPrintPreview_new_3, 2461).
--define(wxPrintPreview_destruct, 2463).
--define(wxPrintPreview_GetCanvas, 2464).
--define(wxPrintPreview_GetCurrentPage, 2465).
--define(wxPrintPreview_GetFrame, 2466).
--define(wxPrintPreview_GetMaxPage, 2467).
--define(wxPrintPreview_GetMinPage, 2468).
--define(wxPrintPreview_GetPrintout, 2469).
--define(wxPrintPreview_GetPrintoutForPrinting, 2470).
--define(wxPrintPreview_IsOk, 2471).
--define(wxPrintPreview_PaintPage, 2472).
--define(wxPrintPreview_Print, 2473).
--define(wxPrintPreview_RenderPage, 2474).
--define(wxPrintPreview_SetCanvas, 2475).
--define(wxPrintPreview_SetCurrentPage, 2476).
--define(wxPrintPreview_SetFrame, 2477).
--define(wxPrintPreview_SetPrintout, 2478).
--define(wxPrintPreview_SetZoom, 2479).
--define(wxPreviewFrame_new, 2480).
--define(wxPreviewFrame_destruct, 2481).
--define(wxPreviewFrame_CreateControlBar, 2482).
--define(wxPreviewFrame_CreateCanvas, 2483).
--define(wxPreviewFrame_Initialize, 2484).
--define(wxPreviewFrame_OnCloseWindow, 2485).
--define(wxPreviewControlBar_new, 2486).
--define(wxPreviewControlBar_destruct, 2487).
--define(wxPreviewControlBar_CreateButtons, 2488).
--define(wxPreviewControlBar_GetPrintPreview, 2489).
--define(wxPreviewControlBar_GetZoomControl, 2490).
--define(wxPreviewControlBar_SetZoomControl, 2491).
--define(wxPrinter_new, 2493).
--define(wxPrinter_CreateAbortWindow, 2494).
--define(wxPrinter_GetAbort, 2495).
--define(wxPrinter_GetLastError, 2496).
--define(wxPrinter_GetPrintDialogData, 2497).
--define(wxPrinter_Print, 2498).
--define(wxPrinter_PrintDialog, 2499).
--define(wxPrinter_ReportError, 2500).
--define(wxPrinter_Setup, 2501).
--define(wxPrinter_destroy, 2502).
--define(wxXmlResource_new_1, 2503).
--define(wxXmlResource_new_2, 2504).
--define(wxXmlResource_destruct, 2505).
--define(wxXmlResource_AttachUnknownControl, 2506).
--define(wxXmlResource_ClearHandlers, 2507).
--define(wxXmlResource_CompareVersion, 2508).
--define(wxXmlResource_Get, 2509).
--define(wxXmlResource_GetFlags, 2510).
--define(wxXmlResource_GetVersion, 2511).
--define(wxXmlResource_GetXRCID, 2512).
--define(wxXmlResource_InitAllHandlers, 2513).
--define(wxXmlResource_Load, 2514).
--define(wxXmlResource_LoadBitmap, 2515).
--define(wxXmlResource_LoadDialog_2, 2516).
--define(wxXmlResource_LoadDialog_3, 2517).
--define(wxXmlResource_LoadFrame_2, 2518).
--define(wxXmlResource_LoadFrame_3, 2519).
--define(wxXmlResource_LoadIcon, 2520).
--define(wxXmlResource_LoadMenu, 2521).
--define(wxXmlResource_LoadMenuBar_2, 2522).
--define(wxXmlResource_LoadMenuBar_1, 2523).
--define(wxXmlResource_LoadPanel_2, 2524).
--define(wxXmlResource_LoadPanel_3, 2525).
--define(wxXmlResource_LoadToolBar, 2526).
--define(wxXmlResource_Set, 2527).
--define(wxXmlResource_SetFlags, 2528).
--define(wxXmlResource_Unload, 2529).
--define(wxXmlResource_xrcctrl, 2530).
--define(wxHtmlEasyPrinting_new, 2531).
--define(wxHtmlEasyPrinting_destruct, 2532).
--define(wxHtmlEasyPrinting_GetPrintData, 2533).
--define(wxHtmlEasyPrinting_GetPageSetupData, 2534).
--define(wxHtmlEasyPrinting_PreviewFile, 2535).
--define(wxHtmlEasyPrinting_PreviewText, 2536).
--define(wxHtmlEasyPrinting_PrintFile, 2537).
--define(wxHtmlEasyPrinting_PrintText, 2538).
--define(wxHtmlEasyPrinting_PageSetup, 2539).
--define(wxHtmlEasyPrinting_SetFonts, 2540).
--define(wxHtmlEasyPrinting_SetHeader, 2541).
--define(wxHtmlEasyPrinting_SetFooter, 2542).
--define(wxGLCanvas_new_2, 2544).
--define(wxGLCanvas_new_3_1, 2545).
--define(wxGLCanvas_new_3_0, 2546).
--define(wxGLCanvas_GetContext, 2547).
--define(wxGLCanvas_SetCurrent, 2549).
--define(wxGLCanvas_SwapBuffers, 2550).
--define(wxGLCanvas_destroy, 2551).
--define(wxAuiManager_new, 2552).
--define(wxAuiManager_destruct, 2553).
--define(wxAuiManager_AddPane_2_1, 2554).
--define(wxAuiManager_AddPane_3, 2555).
--define(wxAuiManager_AddPane_2_0, 2556).
--define(wxAuiManager_DetachPane, 2557).
--define(wxAuiManager_GetAllPanes, 2558).
--define(wxAuiManager_GetArtProvider, 2559).
--define(wxAuiManager_GetDockSizeConstraint, 2560).
--define(wxAuiManager_GetFlags, 2561).
--define(wxAuiManager_GetManagedWindow, 2562).
--define(wxAuiManager_GetManager, 2563).
--define(wxAuiManager_GetPane_1_1, 2564).
--define(wxAuiManager_GetPane_1_0, 2565).
--define(wxAuiManager_HideHint, 2566).
--define(wxAuiManager_InsertPane, 2567).
--define(wxAuiManager_LoadPaneInfo, 2568).
--define(wxAuiManager_LoadPerspective, 2569).
--define(wxAuiManager_SavePaneInfo, 2570).
--define(wxAuiManager_SavePerspective, 2571).
--define(wxAuiManager_SetArtProvider, 2572).
--define(wxAuiManager_SetDockSizeConstraint, 2573).
--define(wxAuiManager_SetFlags, 2574).
--define(wxAuiManager_SetManagedWindow, 2575).
--define(wxAuiManager_ShowHint, 2576).
--define(wxAuiManager_UnInit, 2577).
--define(wxAuiManager_Update, 2578).
--define(wxAuiPaneInfo_new_0, 2579).
--define(wxAuiPaneInfo_new_1, 2580).
--define(wxAuiPaneInfo_destruct, 2581).
--define(wxAuiPaneInfo_BestSize_1, 2582).
--define(wxAuiPaneInfo_BestSize_2, 2583).
--define(wxAuiPaneInfo_Bottom, 2584).
--define(wxAuiPaneInfo_BottomDockable, 2585).
--define(wxAuiPaneInfo_Caption, 2586).
--define(wxAuiPaneInfo_CaptionVisible, 2587).
--define(wxAuiPaneInfo_Centre, 2588).
--define(wxAuiPaneInfo_CentrePane, 2589).
--define(wxAuiPaneInfo_CloseButton, 2590).
--define(wxAuiPaneInfo_DefaultPane, 2591).
--define(wxAuiPaneInfo_DestroyOnClose, 2592).
--define(wxAuiPaneInfo_Direction, 2593).
--define(wxAuiPaneInfo_Dock, 2594).
--define(wxAuiPaneInfo_Dockable, 2595).
--define(wxAuiPaneInfo_Fixed, 2596).
--define(wxAuiPaneInfo_Float, 2597).
--define(wxAuiPaneInfo_Floatable, 2598).
--define(wxAuiPaneInfo_FloatingPosition_1, 2599).
--define(wxAuiPaneInfo_FloatingPosition_2, 2600).
--define(wxAuiPaneInfo_FloatingSize_1, 2601).
--define(wxAuiPaneInfo_FloatingSize_2, 2602).
--define(wxAuiPaneInfo_Gripper, 2603).
--define(wxAuiPaneInfo_GripperTop, 2604).
--define(wxAuiPaneInfo_HasBorder, 2605).
--define(wxAuiPaneInfo_HasCaption, 2606).
--define(wxAuiPaneInfo_HasCloseButton, 2607).
--define(wxAuiPaneInfo_HasFlag, 2608).
--define(wxAuiPaneInfo_HasGripper, 2609).
--define(wxAuiPaneInfo_HasGripperTop, 2610).
--define(wxAuiPaneInfo_HasMaximizeButton, 2611).
--define(wxAuiPaneInfo_HasMinimizeButton, 2612).
--define(wxAuiPaneInfo_HasPinButton, 2613).
--define(wxAuiPaneInfo_Hide, 2614).
--define(wxAuiPaneInfo_IsBottomDockable, 2615).
--define(wxAuiPaneInfo_IsDocked, 2616).
--define(wxAuiPaneInfo_IsFixed, 2617).
--define(wxAuiPaneInfo_IsFloatable, 2618).
--define(wxAuiPaneInfo_IsFloating, 2619).
--define(wxAuiPaneInfo_IsLeftDockable, 2620).
--define(wxAuiPaneInfo_IsMovable, 2621).
--define(wxAuiPaneInfo_IsOk, 2622).
--define(wxAuiPaneInfo_IsResizable, 2623).
--define(wxAuiPaneInfo_IsRightDockable, 2624).
--define(wxAuiPaneInfo_IsShown, 2625).
--define(wxAuiPaneInfo_IsToolbar, 2626).
--define(wxAuiPaneInfo_IsTopDockable, 2627).
--define(wxAuiPaneInfo_Layer, 2628).
--define(wxAuiPaneInfo_Left, 2629).
--define(wxAuiPaneInfo_LeftDockable, 2630).
--define(wxAuiPaneInfo_MaxSize_1, 2631).
--define(wxAuiPaneInfo_MaxSize_2, 2632).
--define(wxAuiPaneInfo_MaximizeButton, 2633).
--define(wxAuiPaneInfo_MinSize_1, 2634).
--define(wxAuiPaneInfo_MinSize_2, 2635).
--define(wxAuiPaneInfo_MinimizeButton, 2636).
--define(wxAuiPaneInfo_Movable, 2637).
--define(wxAuiPaneInfo_Name, 2638).
--define(wxAuiPaneInfo_PaneBorder, 2639).
--define(wxAuiPaneInfo_PinButton, 2640).
--define(wxAuiPaneInfo_Position, 2641).
--define(wxAuiPaneInfo_Resizable, 2642).
--define(wxAuiPaneInfo_Right, 2643).
--define(wxAuiPaneInfo_RightDockable, 2644).
--define(wxAuiPaneInfo_Row, 2645).
--define(wxAuiPaneInfo_SafeSet, 2646).
--define(wxAuiPaneInfo_SetFlag, 2647).
--define(wxAuiPaneInfo_Show, 2648).
--define(wxAuiPaneInfo_ToolbarPane, 2649).
--define(wxAuiPaneInfo_Top, 2650).
--define(wxAuiPaneInfo_TopDockable, 2651).
--define(wxAuiPaneInfo_Window, 2652).
--define(wxAuiPaneInfo_GetWindow, 2653).
--define(wxAuiPaneInfo_GetFrame, 2654).
--define(wxAuiPaneInfo_GetDirection, 2655).
--define(wxAuiPaneInfo_GetLayer, 2656).
--define(wxAuiPaneInfo_GetRow, 2657).
--define(wxAuiPaneInfo_GetPosition, 2658).
--define(wxAuiPaneInfo_GetFloatingPosition, 2659).
--define(wxAuiPaneInfo_GetFloatingSize, 2660).
--define(wxAuiNotebook_new_0, 2661).
--define(wxAuiNotebook_new_2, 2662).
--define(wxAuiNotebook_AddPage, 2663).
--define(wxAuiNotebook_Create, 2664).
--define(wxAuiNotebook_DeletePage, 2665).
--define(wxAuiNotebook_GetArtProvider, 2666).
--define(wxAuiNotebook_GetPage, 2667).
--define(wxAuiNotebook_GetPageBitmap, 2668).
--define(wxAuiNotebook_GetPageCount, 2669).
--define(wxAuiNotebook_GetPageIndex, 2670).
--define(wxAuiNotebook_GetPageText, 2671).
--define(wxAuiNotebook_GetSelection, 2672).
--define(wxAuiNotebook_InsertPage, 2673).
--define(wxAuiNotebook_RemovePage, 2674).
--define(wxAuiNotebook_SetArtProvider, 2675).
--define(wxAuiNotebook_SetFont, 2676).
--define(wxAuiNotebook_SetPageBitmap, 2677).
--define(wxAuiNotebook_SetPageText, 2678).
--define(wxAuiNotebook_SetSelection, 2679).
--define(wxAuiNotebook_SetTabCtrlHeight, 2680).
--define(wxAuiNotebook_SetUniformBitmapSize, 2681).
--define(wxAuiNotebook_destroy, 2682).
--define(wxAuiTabArt_SetFlags, 2683).
--define(wxAuiTabArt_SetMeasuringFont, 2684).
--define(wxAuiTabArt_SetNormalFont, 2685).
--define(wxAuiTabArt_SetSelectedFont, 2686).
--define(wxAuiTabArt_SetColour, 2687).
--define(wxAuiTabArt_SetActiveColour, 2688).
--define(wxAuiDockArt_GetColour, 2689).
--define(wxAuiDockArt_GetFont, 2690).
--define(wxAuiDockArt_GetMetric, 2691).
--define(wxAuiDockArt_SetColour, 2692).
--define(wxAuiDockArt_SetFont, 2693).
--define(wxAuiDockArt_SetMetric, 2694).
--define(wxAuiSimpleTabArt_new, 2695).
--define(wxAuiSimpleTabArt_destroy, 2696).
--define(wxMDIParentFrame_new_0, 2697).
--define(wxMDIParentFrame_new_4, 2698).
--define(wxMDIParentFrame_destruct, 2699).
--define(wxMDIParentFrame_ActivateNext, 2700).
--define(wxMDIParentFrame_ActivatePrevious, 2701).
--define(wxMDIParentFrame_ArrangeIcons, 2702).
--define(wxMDIParentFrame_Cascade, 2703).
--define(wxMDIParentFrame_Create, 2704).
--define(wxMDIParentFrame_GetActiveChild, 2705).
--define(wxMDIParentFrame_GetClientWindow, 2706).
--define(wxMDIParentFrame_Tile, 2707).
--define(wxMDIChildFrame_new_0, 2708).
--define(wxMDIChildFrame_new_4, 2709).
--define(wxMDIChildFrame_destruct, 2710).
--define(wxMDIChildFrame_Activate, 2711).
--define(wxMDIChildFrame_Create, 2712).
--define(wxMDIChildFrame_Maximize, 2713).
--define(wxMDIChildFrame_Restore, 2714).
--define(wxMDIClientWindow_new_0, 2715).
--define(wxMDIClientWindow_new_2, 2716).
--define(wxMDIClientWindow_destruct, 2717).
--define(wxMDIClientWindow_CreateClient, 2718).
--define(wxLayoutAlgorithm_new, 2719).
--define(wxLayoutAlgorithm_LayoutFrame, 2720).
--define(wxLayoutAlgorithm_LayoutMDIFrame, 2721).
--define(wxLayoutAlgorithm_LayoutWindow, 2722).
--define(wxLayoutAlgorithm_destroy, 2723).
--define(wxEvent_GetId, 2724).
--define(wxEvent_GetSkipped, 2725).
--define(wxEvent_GetTimestamp, 2726).
--define(wxEvent_IsCommandEvent, 2727).
--define(wxEvent_ResumePropagation, 2728).
--define(wxEvent_ShouldPropagate, 2729).
--define(wxEvent_Skip, 2730).
--define(wxEvent_StopPropagation, 2731).
--define(wxCommandEvent_getClientData, 2732).
--define(wxCommandEvent_GetExtraLong, 2733).
--define(wxCommandEvent_GetInt, 2734).
--define(wxCommandEvent_GetSelection, 2735).
--define(wxCommandEvent_GetString, 2736).
--define(wxCommandEvent_IsChecked, 2737).
--define(wxCommandEvent_IsSelection, 2738).
--define(wxCommandEvent_SetInt, 2739).
--define(wxCommandEvent_SetString, 2740).
--define(wxScrollEvent_GetOrientation, 2741).
--define(wxScrollEvent_GetPosition, 2742).
--define(wxScrollWinEvent_GetOrientation, 2743).
--define(wxScrollWinEvent_GetPosition, 2744).
--define(wxMouseEvent_AltDown, 2745).
--define(wxMouseEvent_Button, 2746).
--define(wxMouseEvent_ButtonDClick, 2747).
--define(wxMouseEvent_ButtonDown, 2748).
--define(wxMouseEvent_ButtonUp, 2749).
--define(wxMouseEvent_CmdDown, 2750).
--define(wxMouseEvent_ControlDown, 2751).
--define(wxMouseEvent_Dragging, 2752).
--define(wxMouseEvent_Entering, 2753).
--define(wxMouseEvent_GetButton, 2754).
--define(wxMouseEvent_GetPosition, 2757).
--define(wxMouseEvent_GetLogicalPosition, 2758).
--define(wxMouseEvent_GetLinesPerAction, 2759).
--define(wxMouseEvent_GetWheelRotation, 2760).
--define(wxMouseEvent_GetWheelDelta, 2761).
--define(wxMouseEvent_GetX, 2762).
--define(wxMouseEvent_GetY, 2763).
--define(wxMouseEvent_IsButton, 2764).
--define(wxMouseEvent_IsPageScroll, 2765).
--define(wxMouseEvent_Leaving, 2766).
--define(wxMouseEvent_LeftDClick, 2767).
--define(wxMouseEvent_LeftDown, 2768).
--define(wxMouseEvent_LeftIsDown, 2769).
--define(wxMouseEvent_LeftUp, 2770).
--define(wxMouseEvent_MetaDown, 2771).
--define(wxMouseEvent_MiddleDClick, 2772).
--define(wxMouseEvent_MiddleDown, 2773).
--define(wxMouseEvent_MiddleIsDown, 2774).
--define(wxMouseEvent_MiddleUp, 2775).
--define(wxMouseEvent_Moving, 2776).
--define(wxMouseEvent_RightDClick, 2777).
--define(wxMouseEvent_RightDown, 2778).
--define(wxMouseEvent_RightIsDown, 2779).
--define(wxMouseEvent_RightUp, 2780).
--define(wxMouseEvent_ShiftDown, 2781).
--define(wxSetCursorEvent_GetCursor, 2782).
--define(wxSetCursorEvent_GetX, 2783).
--define(wxSetCursorEvent_GetY, 2784).
--define(wxSetCursorEvent_HasCursor, 2785).
--define(wxSetCursorEvent_SetCursor, 2786).
--define(wxKeyEvent_AltDown, 2787).
--define(wxKeyEvent_CmdDown, 2788).
--define(wxKeyEvent_ControlDown, 2789).
--define(wxKeyEvent_GetKeyCode, 2790).
--define(wxKeyEvent_GetModifiers, 2791).
--define(wxKeyEvent_GetPosition, 2794).
--define(wxKeyEvent_GetRawKeyCode, 2795).
--define(wxKeyEvent_GetRawKeyFlags, 2796).
--define(wxKeyEvent_GetUnicodeKey, 2797).
--define(wxKeyEvent_GetX, 2798).
--define(wxKeyEvent_GetY, 2799).
--define(wxKeyEvent_HasModifiers, 2800).
--define(wxKeyEvent_MetaDown, 2801).
--define(wxKeyEvent_ShiftDown, 2802).
--define(wxSizeEvent_GetSize, 2803).
--define(wxMoveEvent_GetPosition, 2804).
--define(wxEraseEvent_GetDC, 2805).
--define(wxFocusEvent_GetWindow, 2806).
--define(wxChildFocusEvent_GetWindow, 2807).
--define(wxMenuEvent_GetMenu, 2808).
--define(wxMenuEvent_GetMenuId, 2809).
--define(wxMenuEvent_IsPopup, 2810).
--define(wxCloseEvent_CanVeto, 2811).
--define(wxCloseEvent_GetLoggingOff, 2812).
--define(wxCloseEvent_SetCanVeto, 2813).
--define(wxCloseEvent_SetLoggingOff, 2814).
--define(wxCloseEvent_Veto, 2815).
--define(wxShowEvent_SetShow, 2816).
--define(wxShowEvent_GetShow, 2817).
--define(wxIconizeEvent_Iconized, 2818).
--define(wxJoystickEvent_ButtonDown, 2819).
--define(wxJoystickEvent_ButtonIsDown, 2820).
--define(wxJoystickEvent_ButtonUp, 2821).
--define(wxJoystickEvent_GetButtonChange, 2822).
--define(wxJoystickEvent_GetButtonState, 2823).
--define(wxJoystickEvent_GetJoystick, 2824).
--define(wxJoystickEvent_GetPosition, 2825).
--define(wxJoystickEvent_GetZPosition, 2826).
--define(wxJoystickEvent_IsButton, 2827).
--define(wxJoystickEvent_IsMove, 2828).
--define(wxJoystickEvent_IsZMove, 2829).
--define(wxUpdateUIEvent_CanUpdate, 2830).
--define(wxUpdateUIEvent_Check, 2831).
--define(wxUpdateUIEvent_Enable, 2832).
--define(wxUpdateUIEvent_Show, 2833).
--define(wxUpdateUIEvent_GetChecked, 2834).
--define(wxUpdateUIEvent_GetEnabled, 2835).
--define(wxUpdateUIEvent_GetShown, 2836).
--define(wxUpdateUIEvent_GetSetChecked, 2837).
--define(wxUpdateUIEvent_GetSetEnabled, 2838).
--define(wxUpdateUIEvent_GetSetShown, 2839).
--define(wxUpdateUIEvent_GetSetText, 2840).
--define(wxUpdateUIEvent_GetText, 2841).
--define(wxUpdateUIEvent_GetMode, 2842).
--define(wxUpdateUIEvent_GetUpdateInterval, 2843).
--define(wxUpdateUIEvent_ResetUpdateTime, 2844).
--define(wxUpdateUIEvent_SetMode, 2845).
--define(wxUpdateUIEvent_SetText, 2846).
--define(wxUpdateUIEvent_SetUpdateInterval, 2847).
--define(wxMouseCaptureChangedEvent_GetCapturedWindow, 2848).
--define(wxPaletteChangedEvent_SetChangedWindow, 2849).
--define(wxPaletteChangedEvent_GetChangedWindow, 2850).
--define(wxQueryNewPaletteEvent_SetPaletteRealized, 2851).
--define(wxQueryNewPaletteEvent_GetPaletteRealized, 2852).
--define(wxNavigationKeyEvent_GetDirection, 2853).
--define(wxNavigationKeyEvent_SetDirection, 2854).
--define(wxNavigationKeyEvent_IsWindowChange, 2855).
--define(wxNavigationKeyEvent_SetWindowChange, 2856).
--define(wxNavigationKeyEvent_IsFromTab, 2857).
--define(wxNavigationKeyEvent_SetFromTab, 2858).
--define(wxNavigationKeyEvent_GetCurrentFocus, 2859).
--define(wxNavigationKeyEvent_SetCurrentFocus, 2860).
--define(wxHelpEvent_GetOrigin, 2861).
--define(wxHelpEvent_GetPosition, 2862).
--define(wxHelpEvent_SetOrigin, 2863).
--define(wxHelpEvent_SetPosition, 2864).
--define(wxContextMenuEvent_GetPosition, 2865).
--define(wxContextMenuEvent_SetPosition, 2866).
--define(wxIdleEvent_CanSend, 2867).
--define(wxIdleEvent_GetMode, 2868).
--define(wxIdleEvent_RequestMore, 2869).
--define(wxIdleEvent_MoreRequested, 2870).
--define(wxIdleEvent_SetMode, 2871).
--define(wxGridEvent_AltDown, 2872).
--define(wxGridEvent_ControlDown, 2873).
--define(wxGridEvent_GetCol, 2874).
--define(wxGridEvent_GetPosition, 2875).
--define(wxGridEvent_GetRow, 2876).
--define(wxGridEvent_MetaDown, 2877).
--define(wxGridEvent_Selecting, 2878).
--define(wxGridEvent_ShiftDown, 2879).
--define(wxNotifyEvent_Allow, 2880).
--define(wxNotifyEvent_IsAllowed, 2881).
--define(wxNotifyEvent_Veto, 2882).
--define(wxSashEvent_GetEdge, 2883).
--define(wxSashEvent_GetDragRect, 2884).
--define(wxSashEvent_GetDragStatus, 2885).
--define(wxListEvent_GetCacheFrom, 2886).
--define(wxListEvent_GetCacheTo, 2887).
--define(wxListEvent_GetKeyCode, 2888).
--define(wxListEvent_GetIndex, 2889).
--define(wxListEvent_GetColumn, 2890).
--define(wxListEvent_GetPoint, 2891).
--define(wxListEvent_GetLabel, 2892).
--define(wxListEvent_GetText, 2893).
--define(wxListEvent_GetImage, 2894).
--define(wxListEvent_GetData, 2895).
--define(wxListEvent_GetMask, 2896).
--define(wxListEvent_GetItem, 2897).
--define(wxListEvent_IsEditCancelled, 2898).
--define(wxDateEvent_GetDate, 2899).
--define(wxCalendarEvent_GetWeekDay, 2900).
--define(wxFileDirPickerEvent_GetPath, 2901).
--define(wxColourPickerEvent_GetColour, 2902).
--define(wxFontPickerEvent_GetFont, 2903).
--define(wxStyledTextEvent_GetPosition, 2904).
--define(wxStyledTextEvent_GetKey, 2905).
--define(wxStyledTextEvent_GetModifiers, 2906).
--define(wxStyledTextEvent_GetModificationType, 2907).
--define(wxStyledTextEvent_GetText, 2908).
--define(wxStyledTextEvent_GetLength, 2909).
--define(wxStyledTextEvent_GetLinesAdded, 2910).
--define(wxStyledTextEvent_GetLine, 2911).
--define(wxStyledTextEvent_GetFoldLevelNow, 2912).
--define(wxStyledTextEvent_GetFoldLevelPrev, 2913).
--define(wxStyledTextEvent_GetMargin, 2914).
--define(wxStyledTextEvent_GetMessage, 2915).
--define(wxStyledTextEvent_GetWParam, 2916).
--define(wxStyledTextEvent_GetLParam, 2917).
--define(wxStyledTextEvent_GetListType, 2918).
--define(wxStyledTextEvent_GetX, 2919).
--define(wxStyledTextEvent_GetY, 2920).
--define(wxStyledTextEvent_GetDragText, 2921).
--define(wxStyledTextEvent_GetDragAllowMove, 2922).
--define(wxStyledTextEvent_GetDragResult, 2923).
--define(wxStyledTextEvent_GetShift, 2924).
--define(wxStyledTextEvent_GetControl, 2925).
--define(wxStyledTextEvent_GetAlt, 2926).
--define(utils_wxGetKeyState, 2927).
--define(utils_wxGetMousePosition, 2928).
--define(utils_wxGetMouseState, 2929).
--define(utils_wxSetDetectableAutoRepeat, 2930).
--define(utils_wxBell, 2931).
--define(utils_wxFindMenuItemId, 2932).
--define(utils_wxGenericFindWindowAtPoint, 2933).
--define(utils_wxFindWindowAtPoint, 2934).
--define(utils_wxBeginBusyCursor, 2935).
--define(utils_wxEndBusyCursor, 2936).
--define(utils_wxIsBusy, 2937).
--define(utils_wxShutdown, 2938).
--define(utils_wxShell, 2939).
--define(utils_wxLaunchDefaultBrowser, 2940).
--define(utils_wxGetEmailAddress, 2941).
--define(utils_wxGetUserId, 2942).
--define(utils_wxGetHomeDir, 2943).
--define(utils_wxNewId, 2944).
--define(utils_wxRegisterId, 2945).
--define(utils_wxGetCurrentId, 2946).
--define(utils_wxGetOsDescription, 2947).
--define(utils_wxIsPlatformLittleEndian, 2948).
--define(utils_wxIsPlatform64Bit, 2949).
--define(gdicmn_wxDisplaySize, 2950).
--define(gdicmn_wxSetCursor, 2951).
--define(wxPrintout_new, 2952).
--define(wxPrintout_destruct, 2953).
--define(wxPrintout_GetDC, 2954).
--define(wxPrintout_GetPageSizeMM, 2955).
--define(wxPrintout_GetPageSizePixels, 2956).
--define(wxPrintout_GetPaperRectPixels, 2957).
--define(wxPrintout_GetPPIPrinter, 2958).
--define(wxPrintout_GetPPIScreen, 2959).
--define(wxPrintout_GetTitle, 2960).
--define(wxPrintout_IsPreview, 2961).
--define(wxPrintout_FitThisSizeToPaper, 2962).
--define(wxPrintout_FitThisSizeToPage, 2963).
--define(wxPrintout_FitThisSizeToPageMargins, 2964).
--define(wxPrintout_MapScreenSizeToPaper, 2965).
--define(wxPrintout_MapScreenSizeToPage, 2966).
--define(wxPrintout_MapScreenSizeToPageMargins, 2967).
--define(wxPrintout_MapScreenSizeToDevice, 2968).
--define(wxPrintout_GetLogicalPaperRect, 2969).
--define(wxPrintout_GetLogicalPageRect, 2970).
--define(wxPrintout_GetLogicalPageMarginsRect, 2971).
--define(wxPrintout_SetLogicalOrigin, 2972).
--define(wxPrintout_OffsetLogicalOrigin, 2973).
--define(wxStyledTextCtrl_new_2, 2974).
--define(wxStyledTextCtrl_new_0, 2975).
--define(wxStyledTextCtrl_destruct, 2976).
--define(wxStyledTextCtrl_Create, 2977).
--define(wxStyledTextCtrl_AddText, 2978).
--define(wxStyledTextCtrl_AddStyledText, 2979).
--define(wxStyledTextCtrl_InsertText, 2980).
--define(wxStyledTextCtrl_ClearAll, 2981).
--define(wxStyledTextCtrl_ClearDocumentStyle, 2982).
--define(wxStyledTextCtrl_GetLength, 2983).
--define(wxStyledTextCtrl_GetCharAt, 2984).
--define(wxStyledTextCtrl_GetCurrentPos, 2985).
--define(wxStyledTextCtrl_GetAnchor, 2986).
--define(wxStyledTextCtrl_GetStyleAt, 2987).
--define(wxStyledTextCtrl_Redo, 2988).
--define(wxStyledTextCtrl_SetUndoCollection, 2989).
--define(wxStyledTextCtrl_SelectAll, 2990).
--define(wxStyledTextCtrl_SetSavePoint, 2991).
--define(wxStyledTextCtrl_GetStyledText, 2992).
--define(wxStyledTextCtrl_CanRedo, 2993).
--define(wxStyledTextCtrl_MarkerLineFromHandle, 2994).
--define(wxStyledTextCtrl_MarkerDeleteHandle, 2995).
--define(wxStyledTextCtrl_GetUndoCollection, 2996).
--define(wxStyledTextCtrl_GetViewWhiteSpace, 2997).
--define(wxStyledTextCtrl_SetViewWhiteSpace, 2998).
--define(wxStyledTextCtrl_PositionFromPoint, 2999).
--define(wxStyledTextCtrl_PositionFromPointClose, 3000).
--define(wxStyledTextCtrl_GotoLine, 3001).
--define(wxStyledTextCtrl_GotoPos, 3002).
--define(wxStyledTextCtrl_SetAnchor, 3003).
--define(wxStyledTextCtrl_GetCurLine, 3004).
--define(wxStyledTextCtrl_GetEndStyled, 3005).
--define(wxStyledTextCtrl_ConvertEOLs, 3006).
--define(wxStyledTextCtrl_GetEOLMode, 3007).
--define(wxStyledTextCtrl_SetEOLMode, 3008).
--define(wxStyledTextCtrl_StartStyling, 3009).
--define(wxStyledTextCtrl_SetStyling, 3010).
--define(wxStyledTextCtrl_GetBufferedDraw, 3011).
--define(wxStyledTextCtrl_SetBufferedDraw, 3012).
--define(wxStyledTextCtrl_SetTabWidth, 3013).
--define(wxStyledTextCtrl_GetTabWidth, 3014).
--define(wxStyledTextCtrl_SetCodePage, 3015).
--define(wxStyledTextCtrl_MarkerDefine, 3016).
--define(wxStyledTextCtrl_MarkerSetForeground, 3017).
--define(wxStyledTextCtrl_MarkerSetBackground, 3018).
--define(wxStyledTextCtrl_MarkerAdd, 3019).
--define(wxStyledTextCtrl_MarkerDelete, 3020).
--define(wxStyledTextCtrl_MarkerDeleteAll, 3021).
--define(wxStyledTextCtrl_MarkerGet, 3022).
--define(wxStyledTextCtrl_MarkerNext, 3023).
--define(wxStyledTextCtrl_MarkerPrevious, 3024).
--define(wxStyledTextCtrl_MarkerDefineBitmap, 3025).
--define(wxStyledTextCtrl_MarkerAddSet, 3026).
--define(wxStyledTextCtrl_MarkerSetAlpha, 3027).
--define(wxStyledTextCtrl_SetMarginType, 3028).
--define(wxStyledTextCtrl_GetMarginType, 3029).
--define(wxStyledTextCtrl_SetMarginWidth, 3030).
--define(wxStyledTextCtrl_GetMarginWidth, 3031).
--define(wxStyledTextCtrl_SetMarginMask, 3032).
--define(wxStyledTextCtrl_GetMarginMask, 3033).
--define(wxStyledTextCtrl_SetMarginSensitive, 3034).
--define(wxStyledTextCtrl_GetMarginSensitive, 3035).
--define(wxStyledTextCtrl_StyleClearAll, 3036).
--define(wxStyledTextCtrl_StyleSetForeground, 3037).
--define(wxStyledTextCtrl_StyleSetBackground, 3038).
--define(wxStyledTextCtrl_StyleSetBold, 3039).
--define(wxStyledTextCtrl_StyleSetItalic, 3040).
--define(wxStyledTextCtrl_StyleSetSize, 3041).
--define(wxStyledTextCtrl_StyleSetFaceName, 3042).
--define(wxStyledTextCtrl_StyleSetEOLFilled, 3043).
--define(wxStyledTextCtrl_StyleResetDefault, 3044).
--define(wxStyledTextCtrl_StyleSetUnderline, 3045).
--define(wxStyledTextCtrl_StyleSetCase, 3046).
--define(wxStyledTextCtrl_StyleSetHotSpot, 3047).
--define(wxStyledTextCtrl_SetSelForeground, 3048).
--define(wxStyledTextCtrl_SetSelBackground, 3049).
--define(wxStyledTextCtrl_GetSelAlpha, 3050).
--define(wxStyledTextCtrl_SetSelAlpha, 3051).
--define(wxStyledTextCtrl_SetCaretForeground, 3052).
--define(wxStyledTextCtrl_CmdKeyAssign, 3053).
--define(wxStyledTextCtrl_CmdKeyClear, 3054).
--define(wxStyledTextCtrl_CmdKeyClearAll, 3055).
--define(wxStyledTextCtrl_SetStyleBytes, 3056).
--define(wxStyledTextCtrl_StyleSetVisible, 3057).
--define(wxStyledTextCtrl_GetCaretPeriod, 3058).
--define(wxStyledTextCtrl_SetCaretPeriod, 3059).
--define(wxStyledTextCtrl_SetWordChars, 3060).
--define(wxStyledTextCtrl_BeginUndoAction, 3061).
--define(wxStyledTextCtrl_EndUndoAction, 3062).
--define(wxStyledTextCtrl_IndicatorSetStyle, 3063).
--define(wxStyledTextCtrl_IndicatorGetStyle, 3064).
--define(wxStyledTextCtrl_IndicatorSetForeground, 3065).
--define(wxStyledTextCtrl_IndicatorGetForeground, 3066).
--define(wxStyledTextCtrl_SetWhitespaceForeground, 3067).
--define(wxStyledTextCtrl_SetWhitespaceBackground, 3068).
--define(wxStyledTextCtrl_GetStyleBits, 3069).
--define(wxStyledTextCtrl_SetLineState, 3070).
--define(wxStyledTextCtrl_GetLineState, 3071).
--define(wxStyledTextCtrl_GetMaxLineState, 3072).
--define(wxStyledTextCtrl_GetCaretLineVisible, 3073).
--define(wxStyledTextCtrl_SetCaretLineVisible, 3074).
--define(wxStyledTextCtrl_GetCaretLineBackground, 3075).
--define(wxStyledTextCtrl_SetCaretLineBackground, 3076).
--define(wxStyledTextCtrl_AutoCompShow, 3077).
--define(wxStyledTextCtrl_AutoCompCancel, 3078).
--define(wxStyledTextCtrl_AutoCompActive, 3079).
--define(wxStyledTextCtrl_AutoCompPosStart, 3080).
--define(wxStyledTextCtrl_AutoCompComplete, 3081).
--define(wxStyledTextCtrl_AutoCompStops, 3082).
--define(wxStyledTextCtrl_AutoCompSetSeparator, 3083).
--define(wxStyledTextCtrl_AutoCompGetSeparator, 3084).
--define(wxStyledTextCtrl_AutoCompSelect, 3085).
--define(wxStyledTextCtrl_AutoCompSetCancelAtStart, 3086).
--define(wxStyledTextCtrl_AutoCompGetCancelAtStart, 3087).
--define(wxStyledTextCtrl_AutoCompSetFillUps, 3088).
--define(wxStyledTextCtrl_AutoCompSetChooseSingle, 3089).
--define(wxStyledTextCtrl_AutoCompGetChooseSingle, 3090).
--define(wxStyledTextCtrl_AutoCompSetIgnoreCase, 3091).
--define(wxStyledTextCtrl_AutoCompGetIgnoreCase, 3092).
--define(wxStyledTextCtrl_UserListShow, 3093).
--define(wxStyledTextCtrl_AutoCompSetAutoHide, 3094).
--define(wxStyledTextCtrl_AutoCompGetAutoHide, 3095).
--define(wxStyledTextCtrl_AutoCompSetDropRestOfWord, 3096).
--define(wxStyledTextCtrl_AutoCompGetDropRestOfWord, 3097).
--define(wxStyledTextCtrl_RegisterImage, 3098).
--define(wxStyledTextCtrl_ClearRegisteredImages, 3099).
--define(wxStyledTextCtrl_AutoCompGetTypeSeparator, 3100).
--define(wxStyledTextCtrl_AutoCompSetTypeSeparator, 3101).
--define(wxStyledTextCtrl_AutoCompSetMaxWidth, 3102).
--define(wxStyledTextCtrl_AutoCompGetMaxWidth, 3103).
--define(wxStyledTextCtrl_AutoCompSetMaxHeight, 3104).
--define(wxStyledTextCtrl_AutoCompGetMaxHeight, 3105).
--define(wxStyledTextCtrl_SetIndent, 3106).
--define(wxStyledTextCtrl_GetIndent, 3107).
--define(wxStyledTextCtrl_SetUseTabs, 3108).
--define(wxStyledTextCtrl_GetUseTabs, 3109).
--define(wxStyledTextCtrl_SetLineIndentation, 3110).
--define(wxStyledTextCtrl_GetLineIndentation, 3111).
--define(wxStyledTextCtrl_GetLineIndentPosition, 3112).
--define(wxStyledTextCtrl_GetColumn, 3113).
--define(wxStyledTextCtrl_SetUseHorizontalScrollBar, 3114).
--define(wxStyledTextCtrl_GetUseHorizontalScrollBar, 3115).
--define(wxStyledTextCtrl_SetIndentationGuides, 3116).
--define(wxStyledTextCtrl_GetIndentationGuides, 3117).
--define(wxStyledTextCtrl_SetHighlightGuide, 3118).
--define(wxStyledTextCtrl_GetHighlightGuide, 3119).
--define(wxStyledTextCtrl_GetLineEndPosition, 3120).
--define(wxStyledTextCtrl_GetCodePage, 3121).
--define(wxStyledTextCtrl_GetCaretForeground, 3122).
--define(wxStyledTextCtrl_GetReadOnly, 3123).
--define(wxStyledTextCtrl_SetCurrentPos, 3124).
--define(wxStyledTextCtrl_SetSelectionStart, 3125).
--define(wxStyledTextCtrl_GetSelectionStart, 3126).
--define(wxStyledTextCtrl_SetSelectionEnd, 3127).
--define(wxStyledTextCtrl_GetSelectionEnd, 3128).
--define(wxStyledTextCtrl_SetPrintMagnification, 3129).
--define(wxStyledTextCtrl_GetPrintMagnification, 3130).
--define(wxStyledTextCtrl_SetPrintColourMode, 3131).
--define(wxStyledTextCtrl_GetPrintColourMode, 3132).
--define(wxStyledTextCtrl_FindText, 3133).
--define(wxStyledTextCtrl_FormatRange, 3134).
--define(wxStyledTextCtrl_GetFirstVisibleLine, 3135).
--define(wxStyledTextCtrl_GetLine, 3136).
--define(wxStyledTextCtrl_GetLineCount, 3137).
--define(wxStyledTextCtrl_SetMarginLeft, 3138).
--define(wxStyledTextCtrl_GetMarginLeft, 3139).
--define(wxStyledTextCtrl_SetMarginRight, 3140).
--define(wxStyledTextCtrl_GetMarginRight, 3141).
--define(wxStyledTextCtrl_GetModify, 3142).
--define(wxStyledTextCtrl_SetSelection, 3143).
--define(wxStyledTextCtrl_GetSelectedText, 3144).
--define(wxStyledTextCtrl_GetTextRange, 3145).
--define(wxStyledTextCtrl_HideSelection, 3146).
--define(wxStyledTextCtrl_LineFromPosition, 3147).
--define(wxStyledTextCtrl_PositionFromLine, 3148).
--define(wxStyledTextCtrl_LineScroll, 3149).
--define(wxStyledTextCtrl_EnsureCaretVisible, 3150).
--define(wxStyledTextCtrl_ReplaceSelection, 3151).
--define(wxStyledTextCtrl_SetReadOnly, 3152).
--define(wxStyledTextCtrl_CanPaste, 3153).
--define(wxStyledTextCtrl_CanUndo, 3154).
--define(wxStyledTextCtrl_EmptyUndoBuffer, 3155).
--define(wxStyledTextCtrl_Undo, 3156).
--define(wxStyledTextCtrl_Cut, 3157).
--define(wxStyledTextCtrl_Copy, 3158).
--define(wxStyledTextCtrl_Paste, 3159).
--define(wxStyledTextCtrl_Clear, 3160).
--define(wxStyledTextCtrl_SetText, 3161).
--define(wxStyledTextCtrl_GetText, 3162).
--define(wxStyledTextCtrl_GetTextLength, 3163).
--define(wxStyledTextCtrl_GetOvertype, 3164).
--define(wxStyledTextCtrl_SetCaretWidth, 3165).
--define(wxStyledTextCtrl_GetCaretWidth, 3166).
--define(wxStyledTextCtrl_SetTargetStart, 3167).
--define(wxStyledTextCtrl_GetTargetStart, 3168).
--define(wxStyledTextCtrl_SetTargetEnd, 3169).
--define(wxStyledTextCtrl_GetTargetEnd, 3170).
--define(wxStyledTextCtrl_ReplaceTarget, 3171).
--define(wxStyledTextCtrl_SearchInTarget, 3172).
--define(wxStyledTextCtrl_SetSearchFlags, 3173).
--define(wxStyledTextCtrl_GetSearchFlags, 3174).
--define(wxStyledTextCtrl_CallTipShow, 3175).
--define(wxStyledTextCtrl_CallTipCancel, 3176).
--define(wxStyledTextCtrl_CallTipActive, 3177).
--define(wxStyledTextCtrl_CallTipPosAtStart, 3178).
--define(wxStyledTextCtrl_CallTipSetHighlight, 3179).
--define(wxStyledTextCtrl_CallTipSetBackground, 3180).
--define(wxStyledTextCtrl_CallTipSetForeground, 3181).
--define(wxStyledTextCtrl_CallTipSetForegroundHighlight, 3182).
--define(wxStyledTextCtrl_CallTipUseStyle, 3183).
--define(wxStyledTextCtrl_VisibleFromDocLine, 3184).
--define(wxStyledTextCtrl_DocLineFromVisible, 3185).
--define(wxStyledTextCtrl_WrapCount, 3186).
--define(wxStyledTextCtrl_SetFoldLevel, 3187).
--define(wxStyledTextCtrl_GetFoldLevel, 3188).
--define(wxStyledTextCtrl_GetLastChild, 3189).
--define(wxStyledTextCtrl_GetFoldParent, 3190).
--define(wxStyledTextCtrl_ShowLines, 3191).
--define(wxStyledTextCtrl_HideLines, 3192).
--define(wxStyledTextCtrl_GetLineVisible, 3193).
--define(wxStyledTextCtrl_SetFoldExpanded, 3194).
--define(wxStyledTextCtrl_GetFoldExpanded, 3195).
--define(wxStyledTextCtrl_ToggleFold, 3196).
--define(wxStyledTextCtrl_EnsureVisible, 3197).
--define(wxStyledTextCtrl_SetFoldFlags, 3198).
--define(wxStyledTextCtrl_EnsureVisibleEnforcePolicy, 3199).
--define(wxStyledTextCtrl_SetTabIndents, 3200).
--define(wxStyledTextCtrl_GetTabIndents, 3201).
--define(wxStyledTextCtrl_SetBackSpaceUnIndents, 3202).
--define(wxStyledTextCtrl_GetBackSpaceUnIndents, 3203).
--define(wxStyledTextCtrl_SetMouseDwellTime, 3204).
--define(wxStyledTextCtrl_GetMouseDwellTime, 3205).
--define(wxStyledTextCtrl_WordStartPosition, 3206).
--define(wxStyledTextCtrl_WordEndPosition, 3207).
--define(wxStyledTextCtrl_SetWrapMode, 3208).
--define(wxStyledTextCtrl_GetWrapMode, 3209).
--define(wxStyledTextCtrl_SetWrapVisualFlags, 3210).
--define(wxStyledTextCtrl_GetWrapVisualFlags, 3211).
--define(wxStyledTextCtrl_SetWrapVisualFlagsLocation, 3212).
--define(wxStyledTextCtrl_GetWrapVisualFlagsLocation, 3213).
--define(wxStyledTextCtrl_SetWrapStartIndent, 3214).
--define(wxStyledTextCtrl_GetWrapStartIndent, 3215).
--define(wxStyledTextCtrl_SetLayoutCache, 3216).
--define(wxStyledTextCtrl_GetLayoutCache, 3217).
--define(wxStyledTextCtrl_SetScrollWidth, 3218).
--define(wxStyledTextCtrl_GetScrollWidth, 3219).
--define(wxStyledTextCtrl_TextWidth, 3220).
--define(wxStyledTextCtrl_GetEndAtLastLine, 3221).
--define(wxStyledTextCtrl_TextHeight, 3222).
--define(wxStyledTextCtrl_SetUseVerticalScrollBar, 3223).
--define(wxStyledTextCtrl_GetUseVerticalScrollBar, 3224).
--define(wxStyledTextCtrl_AppendText, 3225).
--define(wxStyledTextCtrl_GetTwoPhaseDraw, 3226).
--define(wxStyledTextCtrl_SetTwoPhaseDraw, 3227).
--define(wxStyledTextCtrl_TargetFromSelection, 3228).
--define(wxStyledTextCtrl_LinesJoin, 3229).
--define(wxStyledTextCtrl_LinesSplit, 3230).
--define(wxStyledTextCtrl_SetFoldMarginColour, 3231).
--define(wxStyledTextCtrl_SetFoldMarginHiColour, 3232).
--define(wxStyledTextCtrl_LineDown, 3233).
--define(wxStyledTextCtrl_LineDownExtend, 3234).
--define(wxStyledTextCtrl_LineUp, 3235).
--define(wxStyledTextCtrl_LineUpExtend, 3236).
--define(wxStyledTextCtrl_CharLeft, 3237).
--define(wxStyledTextCtrl_CharLeftExtend, 3238).
--define(wxStyledTextCtrl_CharRight, 3239).
--define(wxStyledTextCtrl_CharRightExtend, 3240).
--define(wxStyledTextCtrl_WordLeft, 3241).
--define(wxStyledTextCtrl_WordLeftExtend, 3242).
--define(wxStyledTextCtrl_WordRight, 3243).
--define(wxStyledTextCtrl_WordRightExtend, 3244).
--define(wxStyledTextCtrl_Home, 3245).
--define(wxStyledTextCtrl_HomeExtend, 3246).
--define(wxStyledTextCtrl_LineEnd, 3247).
--define(wxStyledTextCtrl_LineEndExtend, 3248).
--define(wxStyledTextCtrl_DocumentStart, 3249).
--define(wxStyledTextCtrl_DocumentStartExtend, 3250).
--define(wxStyledTextCtrl_DocumentEnd, 3251).
--define(wxStyledTextCtrl_DocumentEndExtend, 3252).
--define(wxStyledTextCtrl_PageUp, 3253).
--define(wxStyledTextCtrl_PageUpExtend, 3254).
--define(wxStyledTextCtrl_PageDown, 3255).
--define(wxStyledTextCtrl_PageDownExtend, 3256).
--define(wxStyledTextCtrl_EditToggleOvertype, 3257).
--define(wxStyledTextCtrl_Cancel, 3258).
--define(wxStyledTextCtrl_DeleteBack, 3259).
--define(wxStyledTextCtrl_Tab, 3260).
--define(wxStyledTextCtrl_BackTab, 3261).
--define(wxStyledTextCtrl_NewLine, 3262).
--define(wxStyledTextCtrl_FormFeed, 3263).
--define(wxStyledTextCtrl_VCHome, 3264).
--define(wxStyledTextCtrl_VCHomeExtend, 3265).
--define(wxStyledTextCtrl_ZoomIn, 3266).
--define(wxStyledTextCtrl_ZoomOut, 3267).
--define(wxStyledTextCtrl_DelWordLeft, 3268).
--define(wxStyledTextCtrl_DelWordRight, 3269).
--define(wxStyledTextCtrl_LineCut, 3270).
--define(wxStyledTextCtrl_LineDelete, 3271).
--define(wxStyledTextCtrl_LineTranspose, 3272).
--define(wxStyledTextCtrl_LineDuplicate, 3273).
--define(wxStyledTextCtrl_LowerCase, 3274).
--define(wxStyledTextCtrl_UpperCase, 3275).
--define(wxStyledTextCtrl_LineScrollDown, 3276).
--define(wxStyledTextCtrl_LineScrollUp, 3277).
--define(wxStyledTextCtrl_DeleteBackNotLine, 3278).
--define(wxStyledTextCtrl_HomeDisplay, 3279).
--define(wxStyledTextCtrl_HomeDisplayExtend, 3280).
--define(wxStyledTextCtrl_LineEndDisplay, 3281).
--define(wxStyledTextCtrl_LineEndDisplayExtend, 3282).
--define(wxStyledTextCtrl_HomeWrapExtend, 3283).
--define(wxStyledTextCtrl_LineEndWrap, 3284).
--define(wxStyledTextCtrl_LineEndWrapExtend, 3285).
--define(wxStyledTextCtrl_VCHomeWrap, 3286).
--define(wxStyledTextCtrl_VCHomeWrapExtend, 3287).
--define(wxStyledTextCtrl_LineCopy, 3288).
--define(wxStyledTextCtrl_MoveCaretInsideView, 3289).
--define(wxStyledTextCtrl_LineLength, 3290).
--define(wxStyledTextCtrl_BraceHighlight, 3291).
--define(wxStyledTextCtrl_BraceBadLight, 3292).
--define(wxStyledTextCtrl_BraceMatch, 3293).
--define(wxStyledTextCtrl_GetViewEOL, 3294).
--define(wxStyledTextCtrl_SetViewEOL, 3295).
--define(wxStyledTextCtrl_SetModEventMask, 3296).
--define(wxStyledTextCtrl_GetEdgeColumn, 3297).
--define(wxStyledTextCtrl_SetEdgeColumn, 3298).
--define(wxStyledTextCtrl_SetEdgeMode, 3299).
--define(wxStyledTextCtrl_GetEdgeMode, 3300).
--define(wxStyledTextCtrl_GetEdgeColour, 3301).
--define(wxStyledTextCtrl_SetEdgeColour, 3302).
--define(wxStyledTextCtrl_SearchAnchor, 3303).
--define(wxStyledTextCtrl_SearchNext, 3304).
--define(wxStyledTextCtrl_SearchPrev, 3305).
--define(wxStyledTextCtrl_LinesOnScreen, 3306).
--define(wxStyledTextCtrl_UsePopUp, 3307).
--define(wxStyledTextCtrl_SelectionIsRectangle, 3308).
--define(wxStyledTextCtrl_SetZoom, 3309).
--define(wxStyledTextCtrl_GetZoom, 3310).
--define(wxStyledTextCtrl_GetModEventMask, 3311).
--define(wxStyledTextCtrl_SetSTCFocus, 3312).
--define(wxStyledTextCtrl_GetSTCFocus, 3313).
--define(wxStyledTextCtrl_SetStatus, 3314).
--define(wxStyledTextCtrl_GetStatus, 3315).
--define(wxStyledTextCtrl_SetMouseDownCaptures, 3316).
--define(wxStyledTextCtrl_GetMouseDownCaptures, 3317).
--define(wxStyledTextCtrl_SetSTCCursor, 3318).
--define(wxStyledTextCtrl_GetSTCCursor, 3319).
--define(wxStyledTextCtrl_SetControlCharSymbol, 3320).
--define(wxStyledTextCtrl_GetControlCharSymbol, 3321).
--define(wxStyledTextCtrl_WordPartLeft, 3322).
--define(wxStyledTextCtrl_WordPartLeftExtend, 3323).
--define(wxStyledTextCtrl_WordPartRight, 3324).
--define(wxStyledTextCtrl_WordPartRightExtend, 3325).
--define(wxStyledTextCtrl_SetVisiblePolicy, 3326).
--define(wxStyledTextCtrl_DelLineLeft, 3327).
--define(wxStyledTextCtrl_DelLineRight, 3328).
--define(wxStyledTextCtrl_GetXOffset, 3329).
--define(wxStyledTextCtrl_ChooseCaretX, 3330).
--define(wxStyledTextCtrl_SetXCaretPolicy, 3331).
--define(wxStyledTextCtrl_SetYCaretPolicy, 3332).
--define(wxStyledTextCtrl_GetPrintWrapMode, 3333).
--define(wxStyledTextCtrl_SetHotspotActiveForeground, 3334).
--define(wxStyledTextCtrl_SetHotspotActiveBackground, 3335).
--define(wxStyledTextCtrl_SetHotspotActiveUnderline, 3336).
--define(wxStyledTextCtrl_SetHotspotSingleLine, 3337).
--define(wxStyledTextCtrl_ParaDownExtend, 3338).
--define(wxStyledTextCtrl_ParaUp, 3339).
--define(wxStyledTextCtrl_ParaUpExtend, 3340).
--define(wxStyledTextCtrl_PositionBefore, 3341).
--define(wxStyledTextCtrl_PositionAfter, 3342).
--define(wxStyledTextCtrl_CopyRange, 3343).
--define(wxStyledTextCtrl_CopyText, 3344).
--define(wxStyledTextCtrl_SetSelectionMode, 3345).
--define(wxStyledTextCtrl_GetSelectionMode, 3346).
--define(wxStyledTextCtrl_LineDownRectExtend, 3347).
--define(wxStyledTextCtrl_LineUpRectExtend, 3348).
--define(wxStyledTextCtrl_CharLeftRectExtend, 3349).
--define(wxStyledTextCtrl_CharRightRectExtend, 3350).
--define(wxStyledTextCtrl_HomeRectExtend, 3351).
--define(wxStyledTextCtrl_VCHomeRectExtend, 3352).
--define(wxStyledTextCtrl_LineEndRectExtend, 3353).
--define(wxStyledTextCtrl_PageUpRectExtend, 3354).
--define(wxStyledTextCtrl_PageDownRectExtend, 3355).
--define(wxStyledTextCtrl_StutteredPageUp, 3356).
--define(wxStyledTextCtrl_StutteredPageUpExtend, 3357).
--define(wxStyledTextCtrl_StutteredPageDown, 3358).
--define(wxStyledTextCtrl_StutteredPageDownExtend, 3359).
--define(wxStyledTextCtrl_WordLeftEnd, 3360).
--define(wxStyledTextCtrl_WordLeftEndExtend, 3361).
--define(wxStyledTextCtrl_WordRightEnd, 3362).
--define(wxStyledTextCtrl_WordRightEndExtend, 3363).
--define(wxStyledTextCtrl_SetWhitespaceChars, 3364).
--define(wxStyledTextCtrl_SetCharsDefault, 3365).
--define(wxStyledTextCtrl_AutoCompGetCurrent, 3366).
--define(wxStyledTextCtrl_Allocate, 3367).
--define(wxStyledTextCtrl_FindColumn, 3368).
--define(wxStyledTextCtrl_GetCaretSticky, 3369).
--define(wxStyledTextCtrl_SetCaretSticky, 3370).
--define(wxStyledTextCtrl_ToggleCaretSticky, 3371).
--define(wxStyledTextCtrl_SetPasteConvertEndings, 3372).
--define(wxStyledTextCtrl_GetPasteConvertEndings, 3373).
--define(wxStyledTextCtrl_SelectionDuplicate, 3374).
--define(wxStyledTextCtrl_SetCaretLineBackAlpha, 3375).
--define(wxStyledTextCtrl_GetCaretLineBackAlpha, 3376).
--define(wxStyledTextCtrl_StartRecord, 3377).
--define(wxStyledTextCtrl_StopRecord, 3378).
--define(wxStyledTextCtrl_SetLexer, 3379).
--define(wxStyledTextCtrl_GetLexer, 3380).
--define(wxStyledTextCtrl_Colourise, 3381).
--define(wxStyledTextCtrl_SetProperty, 3382).
--define(wxStyledTextCtrl_SetKeyWords, 3383).
--define(wxStyledTextCtrl_SetLexerLanguage, 3384).
--define(wxStyledTextCtrl_GetProperty, 3385).
--define(wxStyledTextCtrl_GetStyleBitsNeeded, 3386).
--define(wxStyledTextCtrl_GetCurrentLine, 3387).
--define(wxStyledTextCtrl_StyleSetSpec, 3388).
--define(wxStyledTextCtrl_StyleSetFont, 3389).
--define(wxStyledTextCtrl_StyleSetFontAttr, 3390).
--define(wxStyledTextCtrl_StyleSetCharacterSet, 3391).
--define(wxStyledTextCtrl_StyleSetFontEncoding, 3392).
--define(wxStyledTextCtrl_CmdKeyExecute, 3393).
--define(wxStyledTextCtrl_SetMargins, 3394).
--define(wxStyledTextCtrl_GetSelection, 3395).
--define(wxStyledTextCtrl_PointFromPosition, 3396).
--define(wxStyledTextCtrl_ScrollToLine, 3397).
--define(wxStyledTextCtrl_ScrollToColumn, 3398).
--define(wxStyledTextCtrl_SetVScrollBar, 3399).
--define(wxStyledTextCtrl_SetHScrollBar, 3400).
--define(wxStyledTextCtrl_GetLastKeydownProcessed, 3401).
--define(wxStyledTextCtrl_SetLastKeydownProcessed, 3402).
--define(wxStyledTextCtrl_SaveFile, 3403).
--define(wxStyledTextCtrl_LoadFile, 3404).
--define(wxStyledTextCtrl_DoDragOver, 3405).
--define(wxStyledTextCtrl_DoDropText, 3406).
--define(wxStyledTextCtrl_GetUseAntiAliasing, 3407).
--define(wxStyledTextCtrl_AddTextRaw, 3408).
--define(wxStyledTextCtrl_InsertTextRaw, 3409).
--define(wxStyledTextCtrl_GetCurLineRaw, 3410).
--define(wxStyledTextCtrl_GetLineRaw, 3411).
--define(wxStyledTextCtrl_GetSelectedTextRaw, 3412).
--define(wxStyledTextCtrl_GetTextRangeRaw, 3413).
--define(wxStyledTextCtrl_SetTextRaw, 3414).
--define(wxStyledTextCtrl_GetTextRaw, 3415).
--define(wxStyledTextCtrl_AppendTextRaw, 3416).
--define(wxArtProvider_GetBitmap, 3417).
--define(wxArtProvider_GetIcon, 3418).
--define(wxTreeEvent_GetKeyCode, 3419).
--define(wxTreeEvent_GetItem, 3420).
--define(wxTreeEvent_GetKeyEvent, 3421).
--define(wxTreeEvent_GetLabel, 3422).
--define(wxTreeEvent_GetOldItem, 3423).
--define(wxTreeEvent_GetPoint, 3424).
--define(wxTreeEvent_IsEditCancelled, 3425).
--define(wxTreeEvent_SetToolTip, 3426).
--define(wxNotebookEvent_GetOldSelection, 3427).
--define(wxNotebookEvent_GetSelection, 3428).
--define(wxNotebookEvent_SetOldSelection, 3429).
--define(wxNotebookEvent_SetSelection, 3430).
--define(wxFileDataObject_new, 3431).
--define(wxFileDataObject_AddFile, 3432).
--define(wxFileDataObject_GetFilenames, 3433).
--define(wxFileDataObject_destroy, 3434).
--define(wxTextDataObject_new, 3435).
--define(wxTextDataObject_GetTextLength, 3436).
--define(wxTextDataObject_GetText, 3437).
--define(wxTextDataObject_SetText, 3438).
--define(wxTextDataObject_destroy, 3439).
--define(wxBitmapDataObject_new_1_1, 3440).
--define(wxBitmapDataObject_new_1_0, 3441).
--define(wxBitmapDataObject_GetBitmap, 3442).
--define(wxBitmapDataObject_SetBitmap, 3443).
--define(wxBitmapDataObject_destroy, 3444).
--define(wxClipboard_new, 3446).
--define(wxClipboard_destruct, 3447).
--define(wxClipboard_AddData, 3448).
--define(wxClipboard_Clear, 3449).
--define(wxClipboard_Close, 3450).
--define(wxClipboard_Flush, 3451).
--define(wxClipboard_GetData, 3452).
--define(wxClipboard_IsOpened, 3453).
--define(wxClipboard_Open, 3454).
--define(wxClipboard_SetData, 3455).
--define(wxClipboard_UsePrimarySelection, 3457).
--define(wxClipboard_IsSupported, 3458).
--define(wxClipboard_Get, 3459).
--define(wxSpinEvent_GetPosition, 3460).
--define(wxSpinEvent_SetPosition, 3461).
--define(wxSplitterWindow_new_0, 3462).
--define(wxSplitterWindow_new_2, 3463).
--define(wxSplitterWindow_destruct, 3464).
--define(wxSplitterWindow_Create, 3465).
--define(wxSplitterWindow_GetMinimumPaneSize, 3466).
--define(wxSplitterWindow_GetSashGravity, 3467).
--define(wxSplitterWindow_GetSashPosition, 3468).
--define(wxSplitterWindow_GetSplitMode, 3469).
--define(wxSplitterWindow_GetWindow1, 3470).
--define(wxSplitterWindow_GetWindow2, 3471).
--define(wxSplitterWindow_Initialize, 3472).
--define(wxSplitterWindow_IsSplit, 3473).
--define(wxSplitterWindow_ReplaceWindow, 3474).
--define(wxSplitterWindow_SetSashGravity, 3475).
--define(wxSplitterWindow_SetSashPosition, 3476).
--define(wxSplitterWindow_SetSashSize, 3477).
--define(wxSplitterWindow_SetMinimumPaneSize, 3478).
--define(wxSplitterWindow_SetSplitMode, 3479).
--define(wxSplitterWindow_SplitHorizontally, 3480).
--define(wxSplitterWindow_SplitVertically, 3481).
--define(wxSplitterWindow_Unsplit, 3482).
--define(wxSplitterWindow_UpdateSize, 3483).
--define(wxSplitterEvent_GetSashPosition, 3484).
--define(wxSplitterEvent_GetX, 3485).
--define(wxSplitterEvent_GetY, 3486).
--define(wxSplitterEvent_GetWindowBeingRemoved, 3487).
--define(wxSplitterEvent_SetSashPosition, 3488).
--define(wxHtmlWindow_new_0, 3489).
--define(wxHtmlWindow_new_2, 3490).
--define(wxHtmlWindow_AppendToPage, 3491).
--define(wxHtmlWindow_GetOpenedAnchor, 3492).
--define(wxHtmlWindow_GetOpenedPage, 3493).
--define(wxHtmlWindow_GetOpenedPageTitle, 3494).
--define(wxHtmlWindow_GetRelatedFrame, 3495).
--define(wxHtmlWindow_HistoryBack, 3496).
--define(wxHtmlWindow_HistoryCanBack, 3497).
--define(wxHtmlWindow_HistoryCanForward, 3498).
--define(wxHtmlWindow_HistoryClear, 3499).
--define(wxHtmlWindow_HistoryForward, 3500).
--define(wxHtmlWindow_LoadFile, 3501).
--define(wxHtmlWindow_LoadPage, 3502).
--define(wxHtmlWindow_SelectAll, 3503).
--define(wxHtmlWindow_SelectionToText, 3504).
--define(wxHtmlWindow_SelectLine, 3505).
--define(wxHtmlWindow_SelectWord, 3506).
--define(wxHtmlWindow_SetBorders, 3507).
--define(wxHtmlWindow_SetFonts, 3508).
--define(wxHtmlWindow_SetPage, 3509).
--define(wxHtmlWindow_SetRelatedFrame, 3510).
--define(wxHtmlWindow_SetRelatedStatusBar, 3511).
--define(wxHtmlWindow_ToText, 3512).
--define(wxHtmlWindow_destroy, 3513).
--define(wxHtmlLinkEvent_GetLinkInfo, 3514).
--define(wxSystemSettings_GetColour, 3515).
--define(wxSystemSettings_GetFont, 3516).
--define(wxSystemSettings_GetMetric, 3517).
--define(wxSystemSettings_GetScreenType, 3518).
--define(wxSystemOptions_GetOption, 3519).
--define(wxSystemOptions_GetOptionInt, 3520).
--define(wxSystemOptions_HasOption, 3521).
--define(wxSystemOptions_IsFalse, 3522).
--define(wxSystemOptions_SetOption_2_1, 3523).
--define(wxSystemOptions_SetOption_2_0, 3524).
--define(wxAuiNotebookEvent_SetSelection, 3525).
--define(wxAuiNotebookEvent_GetSelection, 3526).
--define(wxAuiNotebookEvent_SetOldSelection, 3527).
--define(wxAuiNotebookEvent_GetOldSelection, 3528).
--define(wxAuiNotebookEvent_SetDragSource, 3529).
--define(wxAuiNotebookEvent_GetDragSource, 3530).
--define(wxAuiManagerEvent_SetManager, 3531).
--define(wxAuiManagerEvent_GetManager, 3532).
--define(wxAuiManagerEvent_SetPane, 3533).
--define(wxAuiManagerEvent_GetPane, 3534).
--define(wxAuiManagerEvent_SetButton, 3535).
--define(wxAuiManagerEvent_GetButton, 3536).
--define(wxAuiManagerEvent_SetDC, 3537).
--define(wxAuiManagerEvent_GetDC, 3538).
--define(wxAuiManagerEvent_Veto, 3539).
--define(wxAuiManagerEvent_GetVeto, 3540).
--define(wxAuiManagerEvent_SetCanVeto, 3541).
--define(wxAuiManagerEvent_CanVeto, 3542).
--define(wxLogNull_new, 3543).
--define(wxLogNull_destroy, 3544).
--define(wxTaskBarIcon_new, 3545).
--define(wxTaskBarIcon_destruct, 3546).
--define(wxTaskBarIcon_PopupMenu, 3547).
--define(wxTaskBarIcon_RemoveIcon, 3548).
--define(wxTaskBarIcon_SetIcon, 3549).
--define(wxLocale_new_0, 3550).
--define(wxLocale_new_2, 3552).
--define(wxLocale_destruct, 3553).
--define(wxLocale_Init, 3555).
--define(wxLocale_AddCatalog_1, 3556).
--define(wxLocale_AddCatalog_3, 3557).
--define(wxLocale_AddCatalogLookupPathPrefix, 3558).
--define(wxLocale_GetCanonicalName, 3559).
--define(wxLocale_GetLanguage, 3560).
--define(wxLocale_GetLanguageName, 3561).
--define(wxLocale_GetLocale, 3562).
--define(wxLocale_GetName, 3563).
--define(wxLocale_GetString_2, 3564).
--define(wxLocale_GetString_4, 3565).
--define(wxLocale_GetHeaderValue, 3566).
--define(wxLocale_GetSysName, 3567).
--define(wxLocale_GetSystemEncoding, 3568).
--define(wxLocale_GetSystemEncodingName, 3569).
--define(wxLocale_GetSystemLanguage, 3570).
--define(wxLocale_IsLoaded, 3571).
--define(wxLocale_IsOk, 3572).
--define(wxActivateEvent_GetActive, 3573).
--define(wxPopupWindow_new_2, 3575).
--define(wxPopupWindow_new_0, 3576).
--define(wxPopupWindow_destruct, 3578).
--define(wxPopupWindow_Create, 3579).
--define(wxPopupWindow_Position, 3580).
--define(wxPopupTransientWindow_new_0, 3581).
--define(wxPopupTransientWindow_new_2, 3582).
--define(wxPopupTransientWindow_destruct, 3583).
--define(wxPopupTransientWindow_Popup, 3584).
--define(wxPopupTransientWindow_Dismiss, 3585).
+-define(wxToolBar_AddStretchableSpace, 984).
+-define(wxToolBar_InsertStretchableSpace, 985).
+-define(wxToolBar_DeleteTool, 986).
+-define(wxToolBar_DeleteToolByPos, 987).
+-define(wxToolBar_EnableTool, 988).
+-define(wxToolBar_FindById, 989).
+-define(wxToolBar_FindControl, 990).
+-define(wxToolBar_FindToolForPosition, 991).
+-define(wxToolBar_GetToolSize, 992).
+-define(wxToolBar_GetToolBitmapSize, 993).
+-define(wxToolBar_GetMargins, 994).
+-define(wxToolBar_GetToolEnabled, 995).
+-define(wxToolBar_GetToolLongHelp, 996).
+-define(wxToolBar_GetToolPacking, 997).
+-define(wxToolBar_GetToolPos, 998).
+-define(wxToolBar_GetToolSeparation, 999).
+-define(wxToolBar_GetToolShortHelp, 1000).
+-define(wxToolBar_GetToolState, 1001).
+-define(wxToolBar_InsertControl, 1002).
+-define(wxToolBar_InsertSeparator, 1003).
+-define(wxToolBar_InsertTool_5, 1004).
+-define(wxToolBar_InsertTool_2, 1005).
+-define(wxToolBar_InsertTool_4, 1006).
+-define(wxToolBar_Realize, 1007).
+-define(wxToolBar_RemoveTool, 1008).
+-define(wxToolBar_SetMargins, 1009).
+-define(wxToolBar_SetToolBitmapSize, 1010).
+-define(wxToolBar_SetToolLongHelp, 1011).
+-define(wxToolBar_SetToolPacking, 1012).
+-define(wxToolBar_SetToolShortHelp, 1013).
+-define(wxToolBar_SetToolSeparation, 1014).
+-define(wxToolBar_ToggleTool, 1015).
+-define(wxStatusBar_new_0, 1017).
+-define(wxStatusBar_new_2, 1018).
+-define(wxStatusBar_destruct, 1020).
+-define(wxStatusBar_Create, 1021).
+-define(wxStatusBar_GetFieldRect, 1022).
+-define(wxStatusBar_GetFieldsCount, 1023).
+-define(wxStatusBar_GetStatusText, 1024).
+-define(wxStatusBar_PopStatusText, 1025).
+-define(wxStatusBar_PushStatusText, 1026).
+-define(wxStatusBar_SetFieldsCount, 1027).
+-define(wxStatusBar_SetMinHeight, 1028).
+-define(wxStatusBar_SetStatusText, 1029).
+-define(wxStatusBar_SetStatusWidths, 1030).
+-define(wxStatusBar_SetStatusStyles, 1031).
+-define(wxBitmap_new_0, 1032).
+-define(wxBitmap_new_3, 1033).
+-define(wxBitmap_new_4, 1034).
+-define(wxBitmap_new_2_0, 1035).
+-define(wxBitmap_new_2_1, 1036).
+-define(wxBitmap_destruct, 1037).
+-define(wxBitmap_ConvertToImage, 1038).
+-define(wxBitmap_CopyFromIcon, 1039).
+-define(wxBitmap_Create, 1040).
+-define(wxBitmap_GetDepth, 1041).
+-define(wxBitmap_GetHeight, 1042).
+-define(wxBitmap_GetPalette, 1043).
+-define(wxBitmap_GetMask, 1044).
+-define(wxBitmap_GetWidth, 1045).
+-define(wxBitmap_GetSubBitmap, 1046).
+-define(wxBitmap_LoadFile, 1047).
+-define(wxBitmap_Ok, 1048).
+-define(wxBitmap_SaveFile, 1049).
+-define(wxBitmap_SetDepth, 1050).
+-define(wxBitmap_SetHeight, 1051).
+-define(wxBitmap_SetMask, 1052).
+-define(wxBitmap_SetPalette, 1053).
+-define(wxBitmap_SetWidth, 1054).
+-define(wxIcon_new_0, 1055).
+-define(wxIcon_new_2, 1056).
+-define(wxIcon_new_1, 1057).
+-define(wxIcon_CopyFromBitmap, 1058).
+-define(wxIcon_destroy, 1059).
+-define(wxIconBundle_new_0, 1060).
+-define(wxIconBundle_new_2, 1061).
+-define(wxIconBundle_new_1_0, 1062).
+-define(wxIconBundle_new_1_1, 1063).
+-define(wxIconBundle_destruct, 1064).
+-define(wxIconBundle_AddIcon_2, 1065).
+-define(wxIconBundle_AddIcon_1, 1066).
+-define(wxIconBundle_GetIcon_1_1, 1067).
+-define(wxIconBundle_GetIcon_1_0, 1068).
+-define(wxCursor_new_0, 1069).
+-define(wxCursor_new_1_0, 1070).
+-define(wxCursor_new_1_1, 1071).
+-define(wxCursor_new_4, 1072).
+-define(wxCursor_destruct, 1073).
+-define(wxCursor_Ok, 1074).
+-define(wxMask_new_0, 1075).
+-define(wxMask_new_2_1, 1076).
+-define(wxMask_new_2_0, 1077).
+-define(wxMask_new_1, 1078).
+-define(wxMask_destruct, 1079).
+-define(wxMask_Create_2_1, 1080).
+-define(wxMask_Create_2_0, 1081).
+-define(wxMask_Create_1, 1082).
+-define(wxImage_new_0, 1083).
+-define(wxImage_new_3_0, 1084).
+-define(wxImage_new_4, 1085).
+-define(wxImage_new_5, 1086).
+-define(wxImage_new_2, 1087).
+-define(wxImage_new_3_1, 1088).
+-define(wxImage_Blur, 1089).
+-define(wxImage_BlurHorizontal, 1090).
+-define(wxImage_BlurVertical, 1091).
+-define(wxImage_ConvertAlphaToMask, 1092).
+-define(wxImage_ConvertToGreyscale, 1093).
+-define(wxImage_ConvertToMono, 1094).
+-define(wxImage_Copy, 1095).
+-define(wxImage_Create_3, 1096).
+-define(wxImage_Create_4, 1097).
+-define(wxImage_Create_5, 1098).
+-define(wxImage_Destroy, 1099).
+-define(wxImage_FindFirstUnusedColour, 1100).
+-define(wxImage_GetImageExtWildcard, 1101).
+-define(wxImage_GetAlpha_2, 1102).
+-define(wxImage_GetAlpha_0, 1103).
+-define(wxImage_GetBlue, 1104).
+-define(wxImage_GetData, 1105).
+-define(wxImage_GetGreen, 1106).
+-define(wxImage_GetImageCount, 1107).
+-define(wxImage_GetHeight, 1108).
+-define(wxImage_GetMaskBlue, 1109).
+-define(wxImage_GetMaskGreen, 1110).
+-define(wxImage_GetMaskRed, 1111).
+-define(wxImage_GetOrFindMaskColour, 1112).
+-define(wxImage_GetPalette, 1113).
+-define(wxImage_GetRed, 1114).
+-define(wxImage_GetSubImage, 1115).
+-define(wxImage_GetWidth, 1116).
+-define(wxImage_HasAlpha, 1117).
+-define(wxImage_HasMask, 1118).
+-define(wxImage_GetOption, 1119).
+-define(wxImage_GetOptionInt, 1120).
+-define(wxImage_HasOption, 1121).
+-define(wxImage_InitAlpha, 1122).
+-define(wxImage_InitStandardHandlers, 1123).
+-define(wxImage_IsTransparent, 1124).
+-define(wxImage_LoadFile_2, 1125).
+-define(wxImage_LoadFile_3, 1126).
+-define(wxImage_Ok, 1127).
+-define(wxImage_RemoveHandler, 1128).
+-define(wxImage_Mirror, 1129).
+-define(wxImage_Replace, 1130).
+-define(wxImage_Rescale, 1131).
+-define(wxImage_Resize, 1132).
+-define(wxImage_Rotate, 1133).
+-define(wxImage_RotateHue, 1134).
+-define(wxImage_Rotate90, 1135).
+-define(wxImage_SaveFile_1, 1136).
+-define(wxImage_SaveFile_2_0, 1137).
+-define(wxImage_SaveFile_2_1, 1138).
+-define(wxImage_Scale, 1139).
+-define(wxImage_Size, 1140).
+-define(wxImage_SetAlpha_3, 1141).
+-define(wxImage_SetAlpha_2, 1142).
+-define(wxImage_SetData_2, 1143).
+-define(wxImage_SetData_4, 1144).
+-define(wxImage_SetMask, 1145).
+-define(wxImage_SetMaskColour, 1146).
+-define(wxImage_SetMaskFromImage, 1147).
+-define(wxImage_SetOption_2_1, 1148).
+-define(wxImage_SetOption_2_0, 1149).
+-define(wxImage_SetPalette, 1150).
+-define(wxImage_SetRGB_5, 1151).
+-define(wxImage_SetRGB_4, 1152).
+-define(wxImage_destroy, 1153).
+-define(wxBrush_new_0, 1154).
+-define(wxBrush_new_2, 1155).
+-define(wxBrush_new_1, 1156).
+-define(wxBrush_destruct, 1158).
+-define(wxBrush_GetColour, 1159).
+-define(wxBrush_GetStipple, 1160).
+-define(wxBrush_GetStyle, 1161).
+-define(wxBrush_IsHatch, 1162).
+-define(wxBrush_IsOk, 1163).
+-define(wxBrush_SetColour_1, 1164).
+-define(wxBrush_SetColour_3, 1165).
+-define(wxBrush_SetStipple, 1166).
+-define(wxBrush_SetStyle, 1167).
+-define(wxPen_new_0, 1168).
+-define(wxPen_new_2, 1169).
+-define(wxPen_destruct, 1170).
+-define(wxPen_GetCap, 1171).
+-define(wxPen_GetColour, 1172).
+-define(wxPen_GetJoin, 1173).
+-define(wxPen_GetStyle, 1174).
+-define(wxPen_GetWidth, 1175).
+-define(wxPen_IsOk, 1176).
+-define(wxPen_SetCap, 1177).
+-define(wxPen_SetColour_1, 1178).
+-define(wxPen_SetColour_3, 1179).
+-define(wxPen_SetJoin, 1180).
+-define(wxPen_SetStyle, 1181).
+-define(wxPen_SetWidth, 1182).
+-define(wxRegion_new_0, 1183).
+-define(wxRegion_new_4, 1184).
+-define(wxRegion_new_2, 1185).
+-define(wxRegion_new_1_1, 1186).
+-define(wxRegion_new_1_0, 1188).
+-define(wxRegion_destruct, 1190).
+-define(wxRegion_Clear, 1191).
+-define(wxRegion_Contains_2, 1192).
+-define(wxRegion_Contains_1_0, 1193).
+-define(wxRegion_Contains_4, 1194).
+-define(wxRegion_Contains_1_1, 1195).
+-define(wxRegion_ConvertToBitmap, 1196).
+-define(wxRegion_GetBox, 1197).
+-define(wxRegion_Intersect_4, 1198).
+-define(wxRegion_Intersect_1_1, 1199).
+-define(wxRegion_Intersect_1_0, 1200).
+-define(wxRegion_IsEmpty, 1201).
+-define(wxRegion_Subtract_4, 1202).
+-define(wxRegion_Subtract_1_1, 1203).
+-define(wxRegion_Subtract_1_0, 1204).
+-define(wxRegion_Offset_2, 1205).
+-define(wxRegion_Offset_1, 1206).
+-define(wxRegion_Union_4, 1207).
+-define(wxRegion_Union_1_2, 1208).
+-define(wxRegion_Union_1_1, 1209).
+-define(wxRegion_Union_1_0, 1210).
+-define(wxRegion_Union_3, 1211).
+-define(wxRegion_Xor_4, 1212).
+-define(wxRegion_Xor_1_1, 1213).
+-define(wxRegion_Xor_1_0, 1214).
+-define(wxAcceleratorTable_new_0, 1215).
+-define(wxAcceleratorTable_new_2, 1216).
+-define(wxAcceleratorTable_destruct, 1217).
+-define(wxAcceleratorTable_Ok, 1218).
+-define(wxAcceleratorEntry_new_1_0, 1219).
+-define(wxAcceleratorEntry_new_1_1, 1220).
+-define(wxAcceleratorEntry_GetCommand, 1221).
+-define(wxAcceleratorEntry_GetFlags, 1222).
+-define(wxAcceleratorEntry_GetKeyCode, 1223).
+-define(wxAcceleratorEntry_Set, 1224).
+-define(wxAcceleratorEntry_destroy, 1225).
+-define(wxCaret_new_3, 1230).
+-define(wxCaret_new_2, 1231).
+-define(wxCaret_destruct, 1233).
+-define(wxCaret_Create_3, 1234).
+-define(wxCaret_Create_2, 1235).
+-define(wxCaret_GetBlinkTime, 1236).
+-define(wxCaret_GetPosition, 1238).
+-define(wxCaret_GetSize, 1240).
+-define(wxCaret_GetWindow, 1241).
+-define(wxCaret_Hide, 1242).
+-define(wxCaret_IsOk, 1243).
+-define(wxCaret_IsVisible, 1244).
+-define(wxCaret_Move_2, 1245).
+-define(wxCaret_Move_1, 1246).
+-define(wxCaret_SetBlinkTime, 1247).
+-define(wxCaret_SetSize_2, 1248).
+-define(wxCaret_SetSize_1, 1249).
+-define(wxCaret_Show, 1250).
+-define(wxSizer_Add_2_1, 1251).
+-define(wxSizer_Add_2_0, 1252).
+-define(wxSizer_Add_3, 1253).
+-define(wxSizer_Add_2_3, 1254).
+-define(wxSizer_Add_2_2, 1255).
+-define(wxSizer_AddSpacer, 1256).
+-define(wxSizer_AddStretchSpacer, 1257).
+-define(wxSizer_CalcMin, 1258).
+-define(wxSizer_Clear, 1259).
+-define(wxSizer_Detach_1_2, 1260).
+-define(wxSizer_Detach_1_1, 1261).
+-define(wxSizer_Detach_1_0, 1262).
+-define(wxSizer_Fit, 1263).
+-define(wxSizer_FitInside, 1264).
+-define(wxSizer_GetChildren, 1265).
+-define(wxSizer_GetItem_2_1, 1266).
+-define(wxSizer_GetItem_2_0, 1267).
+-define(wxSizer_GetItem_1, 1268).
+-define(wxSizer_GetSize, 1269).
+-define(wxSizer_GetPosition, 1270).
+-define(wxSizer_GetMinSize, 1271).
+-define(wxSizer_Hide_2_0, 1272).
+-define(wxSizer_Hide_2_1, 1273).
+-define(wxSizer_Hide_1, 1274).
+-define(wxSizer_Insert_3_1, 1275).
+-define(wxSizer_Insert_3_0, 1276).
+-define(wxSizer_Insert_4, 1277).
+-define(wxSizer_Insert_3_3, 1278).
+-define(wxSizer_Insert_3_2, 1279).
+-define(wxSizer_Insert_2, 1280).
+-define(wxSizer_InsertSpacer, 1281).
+-define(wxSizer_InsertStretchSpacer, 1282).
+-define(wxSizer_IsShown_1_2, 1283).
+-define(wxSizer_IsShown_1_1, 1284).
+-define(wxSizer_IsShown_1_0, 1285).
+-define(wxSizer_Layout, 1286).
+-define(wxSizer_Prepend_2_1, 1287).
+-define(wxSizer_Prepend_2_0, 1288).
+-define(wxSizer_Prepend_3, 1289).
+-define(wxSizer_Prepend_2_3, 1290).
+-define(wxSizer_Prepend_2_2, 1291).
+-define(wxSizer_Prepend_1, 1292).
+-define(wxSizer_PrependSpacer, 1293).
+-define(wxSizer_PrependStretchSpacer, 1294).
+-define(wxSizer_RecalcSizes, 1295).
+-define(wxSizer_Remove_1_1, 1296).
+-define(wxSizer_Remove_1_0, 1297).
+-define(wxSizer_Replace_3_1, 1298).
+-define(wxSizer_Replace_3_0, 1299).
+-define(wxSizer_Replace_2, 1300).
+-define(wxSizer_SetDimension, 1301).
+-define(wxSizer_SetMinSize_2, 1302).
+-define(wxSizer_SetMinSize_1, 1303).
+-define(wxSizer_SetItemMinSize_3_2, 1304).
+-define(wxSizer_SetItemMinSize_2_2, 1305).
+-define(wxSizer_SetItemMinSize_3_1, 1306).
+-define(wxSizer_SetItemMinSize_2_1, 1307).
+-define(wxSizer_SetItemMinSize_3_0, 1308).
+-define(wxSizer_SetItemMinSize_2_0, 1309).
+-define(wxSizer_SetSizeHints, 1310).
+-define(wxSizer_SetVirtualSizeHints, 1311).
+-define(wxSizer_Show_2_2, 1312).
+-define(wxSizer_Show_2_1, 1313).
+-define(wxSizer_Show_2_0, 1314).
+-define(wxSizer_Show_1, 1315).
+-define(wxSizerFlags_new, 1316).
+-define(wxSizerFlags_Align, 1317).
+-define(wxSizerFlags_Border_2, 1318).
+-define(wxSizerFlags_Border_1, 1319).
+-define(wxSizerFlags_Center, 1320).
+-define(wxSizerFlags_Centre, 1321).
+-define(wxSizerFlags_Expand, 1322).
+-define(wxSizerFlags_Left, 1323).
+-define(wxSizerFlags_Proportion, 1324).
+-define(wxSizerFlags_Right, 1325).
+-define(wxSizerFlags_destroy, 1326).
+-define(wxSizerItem_new_5_1, 1327).
+-define(wxSizerItem_new_2_1, 1328).
+-define(wxSizerItem_new_5_0, 1329).
+-define(wxSizerItem_new_2_0, 1330).
+-define(wxSizerItem_new_6, 1331).
+-define(wxSizerItem_new_3, 1332).
+-define(wxSizerItem_new_0, 1333).
+-define(wxSizerItem_destruct, 1334).
+-define(wxSizerItem_CalcMin, 1335).
+-define(wxSizerItem_DeleteWindows, 1336).
+-define(wxSizerItem_DetachSizer, 1337).
+-define(wxSizerItem_GetBorder, 1338).
+-define(wxSizerItem_GetFlag, 1339).
+-define(wxSizerItem_GetMinSize, 1340).
+-define(wxSizerItem_GetPosition, 1341).
+-define(wxSizerItem_GetProportion, 1342).
+-define(wxSizerItem_GetRatio, 1343).
+-define(wxSizerItem_GetRect, 1344).
+-define(wxSizerItem_GetSize, 1345).
+-define(wxSizerItem_GetSizer, 1346).
+-define(wxSizerItem_GetSpacer, 1347).
+-define(wxSizerItem_GetUserData, 1348).
+-define(wxSizerItem_GetWindow, 1349).
+-define(wxSizerItem_IsSizer, 1350).
+-define(wxSizerItem_IsShown, 1351).
+-define(wxSizerItem_IsSpacer, 1352).
+-define(wxSizerItem_IsWindow, 1353).
+-define(wxSizerItem_SetBorder, 1354).
+-define(wxSizerItem_SetDimension, 1355).
+-define(wxSizerItem_SetFlag, 1356).
+-define(wxSizerItem_SetInitSize, 1357).
+-define(wxSizerItem_SetMinSize_1, 1358).
+-define(wxSizerItem_SetMinSize_2, 1359).
+-define(wxSizerItem_SetProportion, 1360).
+-define(wxSizerItem_SetRatio_2, 1361).
+-define(wxSizerItem_SetRatio_1_1, 1362).
+-define(wxSizerItem_SetRatio_1_0, 1363).
+-define(wxSizerItem_SetSizer, 1364).
+-define(wxSizerItem_SetSpacer_1, 1365).
+-define(wxSizerItem_SetSpacer_2, 1366).
+-define(wxSizerItem_SetWindow, 1367).
+-define(wxSizerItem_Show, 1368).
+-define(wxBoxSizer_new, 1369).
+-define(wxBoxSizer_GetOrientation, 1370).
+-define(wxBoxSizer_destroy, 1371).
+-define(wxStaticBoxSizer_new_2, 1372).
+-define(wxStaticBoxSizer_new_3, 1373).
+-define(wxStaticBoxSizer_GetStaticBox, 1374).
+-define(wxStaticBoxSizer_destroy, 1375).
+-define(wxGridSizer_new_4, 1376).
+-define(wxGridSizer_new_2, 1377).
+-define(wxGridSizer_GetCols, 1378).
+-define(wxGridSizer_GetHGap, 1379).
+-define(wxGridSizer_GetRows, 1380).
+-define(wxGridSizer_GetVGap, 1381).
+-define(wxGridSizer_SetCols, 1382).
+-define(wxGridSizer_SetHGap, 1383).
+-define(wxGridSizer_SetRows, 1384).
+-define(wxGridSizer_SetVGap, 1385).
+-define(wxGridSizer_destroy, 1386).
+-define(wxFlexGridSizer_new_4, 1387).
+-define(wxFlexGridSizer_new_2, 1388).
+-define(wxFlexGridSizer_AddGrowableCol, 1389).
+-define(wxFlexGridSizer_AddGrowableRow, 1390).
+-define(wxFlexGridSizer_GetFlexibleDirection, 1391).
+-define(wxFlexGridSizer_GetNonFlexibleGrowMode, 1392).
+-define(wxFlexGridSizer_RemoveGrowableCol, 1393).
+-define(wxFlexGridSizer_RemoveGrowableRow, 1394).
+-define(wxFlexGridSizer_SetFlexibleDirection, 1395).
+-define(wxFlexGridSizer_SetNonFlexibleGrowMode, 1396).
+-define(wxFlexGridSizer_destroy, 1397).
+-define(wxGridBagSizer_new, 1398).
+-define(wxGridBagSizer_Add_3_2, 1399).
+-define(wxGridBagSizer_Add_3_1, 1400).
+-define(wxGridBagSizer_Add_4, 1401).
+-define(wxGridBagSizer_Add_1_0, 1402).
+-define(wxGridBagSizer_Add_2_1, 1403).
+-define(wxGridBagSizer_Add_2_0, 1404).
+-define(wxGridBagSizer_Add_3_0, 1405).
+-define(wxGridBagSizer_Add_1_1, 1406).
+-define(wxGridBagSizer_CalcMin, 1407).
+-define(wxGridBagSizer_CheckForIntersection_2, 1408).
+-define(wxGridBagSizer_CheckForIntersection_3, 1409).
+-define(wxGridBagSizer_FindItem_1_1, 1410).
+-define(wxGridBagSizer_FindItem_1_0, 1411).
+-define(wxGridBagSizer_FindItemAtPoint, 1412).
+-define(wxGridBagSizer_FindItemAtPosition, 1413).
+-define(wxGridBagSizer_FindItemWithData, 1414).
+-define(wxGridBagSizer_GetCellSize, 1415).
+-define(wxGridBagSizer_GetEmptyCellSize, 1416).
+-define(wxGridBagSizer_GetItemPosition_1_2, 1417).
+-define(wxGridBagSizer_GetItemPosition_1_1, 1418).
+-define(wxGridBagSizer_GetItemPosition_1_0, 1419).
+-define(wxGridBagSizer_GetItemSpan_1_2, 1420).
+-define(wxGridBagSizer_GetItemSpan_1_1, 1421).
+-define(wxGridBagSizer_GetItemSpan_1_0, 1422).
+-define(wxGridBagSizer_SetEmptyCellSize, 1423).
+-define(wxGridBagSizer_SetItemPosition_2_2, 1424).
+-define(wxGridBagSizer_SetItemPosition_2_1, 1425).
+-define(wxGridBagSizer_SetItemPosition_2_0, 1426).
+-define(wxGridBagSizer_SetItemSpan_2_2, 1427).
+-define(wxGridBagSizer_SetItemSpan_2_1, 1428).
+-define(wxGridBagSizer_SetItemSpan_2_0, 1429).
+-define(wxGridBagSizer_destroy, 1430).
+-define(wxStdDialogButtonSizer_new, 1431).
+-define(wxStdDialogButtonSizer_AddButton, 1432).
+-define(wxStdDialogButtonSizer_Realize, 1433).
+-define(wxStdDialogButtonSizer_SetAffirmativeButton, 1434).
+-define(wxStdDialogButtonSizer_SetCancelButton, 1435).
+-define(wxStdDialogButtonSizer_SetNegativeButton, 1436).
+-define(wxStdDialogButtonSizer_destroy, 1437).
+-define(wxFont_new_0, 1438).
+-define(wxFont_new_1, 1439).
+-define(wxFont_new_5, 1440).
+-define(wxFont_destruct, 1442).
+-define(wxFont_IsFixedWidth, 1443).
+-define(wxFont_GetDefaultEncoding, 1444).
+-define(wxFont_GetFaceName, 1445).
+-define(wxFont_GetFamily, 1446).
+-define(wxFont_GetNativeFontInfoDesc, 1447).
+-define(wxFont_GetNativeFontInfoUserDesc, 1448).
+-define(wxFont_GetPointSize, 1449).
+-define(wxFont_GetStyle, 1450).
+-define(wxFont_GetUnderlined, 1451).
+-define(wxFont_GetWeight, 1452).
+-define(wxFont_Ok, 1453).
+-define(wxFont_SetDefaultEncoding, 1454).
+-define(wxFont_SetFaceName, 1455).
+-define(wxFont_SetFamily, 1456).
+-define(wxFont_SetPointSize, 1457).
+-define(wxFont_SetStyle, 1458).
+-define(wxFont_SetUnderlined, 1459).
+-define(wxFont_SetWeight, 1460).
+-define(wxToolTip_Enable, 1461).
+-define(wxToolTip_SetDelay, 1462).
+-define(wxToolTip_new, 1463).
+-define(wxToolTip_SetTip, 1464).
+-define(wxToolTip_GetTip, 1465).
+-define(wxToolTip_GetWindow, 1466).
+-define(wxToolTip_destroy, 1467).
+-define(wxButton_new_3, 1469).
+-define(wxButton_new_0, 1470).
+-define(wxButton_destruct, 1471).
+-define(wxButton_Create, 1472).
+-define(wxButton_GetDefaultSize, 1473).
+-define(wxButton_SetDefault, 1474).
+-define(wxButton_SetLabel, 1475).
+-define(wxBitmapButton_new_4, 1477).
+-define(wxBitmapButton_new_0, 1478).
+-define(wxBitmapButton_Create, 1479).
+-define(wxBitmapButton_GetBitmapDisabled, 1480).
+-define(wxBitmapButton_GetBitmapFocus, 1482).
+-define(wxBitmapButton_GetBitmapLabel, 1484).
+-define(wxBitmapButton_GetBitmapSelected, 1486).
+-define(wxBitmapButton_SetBitmapDisabled, 1488).
+-define(wxBitmapButton_SetBitmapFocus, 1489).
+-define(wxBitmapButton_SetBitmapLabel, 1490).
+-define(wxBitmapButton_SetBitmapSelected, 1491).
+-define(wxBitmapButton_destroy, 1492).
+-define(wxToggleButton_new_0, 1493).
+-define(wxToggleButton_new_4, 1494).
+-define(wxToggleButton_Create, 1495).
+-define(wxToggleButton_GetValue, 1496).
+-define(wxToggleButton_SetValue, 1497).
+-define(wxToggleButton_destroy, 1498).
+-define(wxCalendarCtrl_new_0, 1499).
+-define(wxCalendarCtrl_new_3, 1500).
+-define(wxCalendarCtrl_Create, 1501).
+-define(wxCalendarCtrl_destruct, 1502).
+-define(wxCalendarCtrl_SetDate, 1503).
+-define(wxCalendarCtrl_GetDate, 1504).
+-define(wxCalendarCtrl_EnableYearChange, 1505).
+-define(wxCalendarCtrl_EnableMonthChange, 1506).
+-define(wxCalendarCtrl_EnableHolidayDisplay, 1507).
+-define(wxCalendarCtrl_SetHeaderColours, 1508).
+-define(wxCalendarCtrl_GetHeaderColourFg, 1509).
+-define(wxCalendarCtrl_GetHeaderColourBg, 1510).
+-define(wxCalendarCtrl_SetHighlightColours, 1511).
+-define(wxCalendarCtrl_GetHighlightColourFg, 1512).
+-define(wxCalendarCtrl_GetHighlightColourBg, 1513).
+-define(wxCalendarCtrl_SetHolidayColours, 1514).
+-define(wxCalendarCtrl_GetHolidayColourFg, 1515).
+-define(wxCalendarCtrl_GetHolidayColourBg, 1516).
+-define(wxCalendarCtrl_GetAttr, 1517).
+-define(wxCalendarCtrl_SetAttr, 1518).
+-define(wxCalendarCtrl_SetHoliday, 1519).
+-define(wxCalendarCtrl_ResetAttr, 1520).
+-define(wxCalendarCtrl_HitTest, 1521).
+-define(wxCalendarDateAttr_new_0, 1522).
+-define(wxCalendarDateAttr_new_2_1, 1523).
+-define(wxCalendarDateAttr_new_2_0, 1524).
+-define(wxCalendarDateAttr_SetTextColour, 1525).
+-define(wxCalendarDateAttr_SetBackgroundColour, 1526).
+-define(wxCalendarDateAttr_SetBorderColour, 1527).
+-define(wxCalendarDateAttr_SetFont, 1528).
+-define(wxCalendarDateAttr_SetBorder, 1529).
+-define(wxCalendarDateAttr_SetHoliday, 1530).
+-define(wxCalendarDateAttr_HasTextColour, 1531).
+-define(wxCalendarDateAttr_HasBackgroundColour, 1532).
+-define(wxCalendarDateAttr_HasBorderColour, 1533).
+-define(wxCalendarDateAttr_HasFont, 1534).
+-define(wxCalendarDateAttr_HasBorder, 1535).
+-define(wxCalendarDateAttr_IsHoliday, 1536).
+-define(wxCalendarDateAttr_GetTextColour, 1537).
+-define(wxCalendarDateAttr_GetBackgroundColour, 1538).
+-define(wxCalendarDateAttr_GetBorderColour, 1539).
+-define(wxCalendarDateAttr_GetFont, 1540).
+-define(wxCalendarDateAttr_GetBorder, 1541).
+-define(wxCalendarDateAttr_destroy, 1542).
+-define(wxCheckBox_new_4, 1544).
+-define(wxCheckBox_new_0, 1545).
+-define(wxCheckBox_Create, 1546).
+-define(wxCheckBox_GetValue, 1547).
+-define(wxCheckBox_Get3StateValue, 1548).
+-define(wxCheckBox_Is3rdStateAllowedForUser, 1549).
+-define(wxCheckBox_Is3State, 1550).
+-define(wxCheckBox_IsChecked, 1551).
+-define(wxCheckBox_SetValue, 1552).
+-define(wxCheckBox_Set3StateValue, 1553).
+-define(wxCheckBox_destroy, 1554).
+-define(wxCheckListBox_new_0, 1555).
+-define(wxCheckListBox_new_3, 1557).
+-define(wxCheckListBox_Check, 1558).
+-define(wxCheckListBox_IsChecked, 1559).
+-define(wxCheckListBox_destroy, 1560).
+-define(wxChoice_new_3, 1563).
+-define(wxChoice_new_0, 1564).
+-define(wxChoice_destruct, 1566).
+-define(wxChoice_Create, 1568).
+-define(wxChoice_Delete, 1569).
+-define(wxChoice_GetColumns, 1570).
+-define(wxChoice_SetColumns, 1571).
+-define(wxComboBox_new_0, 1572).
+-define(wxComboBox_new_3, 1574).
+-define(wxComboBox_destruct, 1575).
+-define(wxComboBox_Create, 1577).
+-define(wxComboBox_CanCopy, 1578).
+-define(wxComboBox_CanCut, 1579).
+-define(wxComboBox_CanPaste, 1580).
+-define(wxComboBox_CanRedo, 1581).
+-define(wxComboBox_CanUndo, 1582).
+-define(wxComboBox_Copy, 1583).
+-define(wxComboBox_Cut, 1584).
+-define(wxComboBox_GetInsertionPoint, 1585).
+-define(wxComboBox_GetLastPosition, 1586).
+-define(wxComboBox_GetValue, 1587).
+-define(wxComboBox_Paste, 1588).
+-define(wxComboBox_Redo, 1589).
+-define(wxComboBox_Replace, 1590).
+-define(wxComboBox_Remove, 1591).
+-define(wxComboBox_SetInsertionPoint, 1592).
+-define(wxComboBox_SetInsertionPointEnd, 1593).
+-define(wxComboBox_SetSelection_1, 1594).
+-define(wxComboBox_SetSelection_2, 1595).
+-define(wxComboBox_SetValue, 1596).
+-define(wxComboBox_Undo, 1597).
+-define(wxGauge_new_0, 1598).
+-define(wxGauge_new_4, 1599).
+-define(wxGauge_Create, 1600).
+-define(wxGauge_GetBezelFace, 1601).
+-define(wxGauge_GetRange, 1602).
+-define(wxGauge_GetShadowWidth, 1603).
+-define(wxGauge_GetValue, 1604).
+-define(wxGauge_IsVertical, 1605).
+-define(wxGauge_SetBezelFace, 1606).
+-define(wxGauge_SetRange, 1607).
+-define(wxGauge_SetShadowWidth, 1608).
+-define(wxGauge_SetValue, 1609).
+-define(wxGauge_Pulse, 1610).
+-define(wxGauge_destroy, 1611).
+-define(wxGenericDirCtrl_new_0, 1612).
+-define(wxGenericDirCtrl_new_2, 1613).
+-define(wxGenericDirCtrl_destruct, 1614).
+-define(wxGenericDirCtrl_Create, 1615).
+-define(wxGenericDirCtrl_Init, 1616).
+-define(wxGenericDirCtrl_CollapseTree, 1617).
+-define(wxGenericDirCtrl_ExpandPath, 1618).
+-define(wxGenericDirCtrl_GetDefaultPath, 1619).
+-define(wxGenericDirCtrl_GetPath, 1620).
+-define(wxGenericDirCtrl_GetFilePath, 1621).
+-define(wxGenericDirCtrl_GetFilter, 1622).
+-define(wxGenericDirCtrl_GetFilterIndex, 1623).
+-define(wxGenericDirCtrl_GetRootId, 1624).
+-define(wxGenericDirCtrl_GetTreeCtrl, 1625).
+-define(wxGenericDirCtrl_ReCreateTree, 1626).
+-define(wxGenericDirCtrl_SetDefaultPath, 1627).
+-define(wxGenericDirCtrl_SetFilter, 1628).
+-define(wxGenericDirCtrl_SetFilterIndex, 1629).
+-define(wxGenericDirCtrl_SetPath, 1630).
+-define(wxStaticBox_new_4, 1632).
+-define(wxStaticBox_new_0, 1633).
+-define(wxStaticBox_Create, 1634).
+-define(wxStaticBox_destroy, 1635).
+-define(wxStaticLine_new_2, 1637).
+-define(wxStaticLine_new_0, 1638).
+-define(wxStaticLine_Create, 1639).
+-define(wxStaticLine_IsVertical, 1640).
+-define(wxStaticLine_GetDefaultSize, 1641).
+-define(wxStaticLine_destroy, 1642).
+-define(wxListBox_new_3, 1645).
+-define(wxListBox_new_0, 1646).
+-define(wxListBox_destruct, 1648).
+-define(wxListBox_Create, 1650).
+-define(wxListBox_Deselect, 1651).
+-define(wxListBox_GetSelections, 1652).
+-define(wxListBox_InsertItems, 1653).
+-define(wxListBox_IsSelected, 1654).
+-define(wxListBox_Set, 1655).
+-define(wxListBox_HitTest, 1656).
+-define(wxListBox_SetFirstItem_1_0, 1657).
+-define(wxListBox_SetFirstItem_1_1, 1658).
+-define(wxListCtrl_new_0, 1659).
+-define(wxListCtrl_new_2, 1660).
+-define(wxListCtrl_Arrange, 1661).
+-define(wxListCtrl_AssignImageList, 1662).
+-define(wxListCtrl_ClearAll, 1663).
+-define(wxListCtrl_Create, 1664).
+-define(wxListCtrl_DeleteAllItems, 1665).
+-define(wxListCtrl_DeleteColumn, 1666).
+-define(wxListCtrl_DeleteItem, 1667).
+-define(wxListCtrl_EditLabel, 1668).
+-define(wxListCtrl_EnsureVisible, 1669).
+-define(wxListCtrl_FindItem_3_0, 1670).
+-define(wxListCtrl_FindItem_3_1, 1671).
+-define(wxListCtrl_GetColumn, 1672).
+-define(wxListCtrl_GetColumnCount, 1673).
+-define(wxListCtrl_GetColumnWidth, 1674).
+-define(wxListCtrl_GetCountPerPage, 1675).
+-define(wxListCtrl_GetEditControl, 1676).
+-define(wxListCtrl_GetImageList, 1677).
+-define(wxListCtrl_GetItem, 1678).
+-define(wxListCtrl_GetItemBackgroundColour, 1679).
+-define(wxListCtrl_GetItemCount, 1680).
+-define(wxListCtrl_GetItemData, 1681).
+-define(wxListCtrl_GetItemFont, 1682).
+-define(wxListCtrl_GetItemPosition, 1683).
+-define(wxListCtrl_GetItemRect, 1684).
+-define(wxListCtrl_GetItemSpacing, 1685).
+-define(wxListCtrl_GetItemState, 1686).
+-define(wxListCtrl_GetItemText, 1687).
+-define(wxListCtrl_GetItemTextColour, 1688).
+-define(wxListCtrl_GetNextItem, 1689).
+-define(wxListCtrl_GetSelectedItemCount, 1690).
+-define(wxListCtrl_GetTextColour, 1691).
+-define(wxListCtrl_GetTopItem, 1692).
+-define(wxListCtrl_GetViewRect, 1693).
+-define(wxListCtrl_HitTest, 1694).
+-define(wxListCtrl_InsertColumn_2, 1695).
+-define(wxListCtrl_InsertColumn_3, 1696).
+-define(wxListCtrl_InsertItem_1, 1697).
+-define(wxListCtrl_InsertItem_2_1, 1698).
+-define(wxListCtrl_InsertItem_2_0, 1699).
+-define(wxListCtrl_InsertItem_3, 1700).
+-define(wxListCtrl_RefreshItem, 1701).
+-define(wxListCtrl_RefreshItems, 1702).
+-define(wxListCtrl_ScrollList, 1703).
+-define(wxListCtrl_SetBackgroundColour, 1704).
+-define(wxListCtrl_SetColumn, 1705).
+-define(wxListCtrl_SetColumnWidth, 1706).
+-define(wxListCtrl_SetImageList, 1707).
+-define(wxListCtrl_SetItem_1, 1708).
+-define(wxListCtrl_SetItem_4, 1709).
+-define(wxListCtrl_SetItemBackgroundColour, 1710).
+-define(wxListCtrl_SetItemCount, 1711).
+-define(wxListCtrl_SetItemData, 1712).
+-define(wxListCtrl_SetItemFont, 1713).
+-define(wxListCtrl_SetItemImage, 1714).
+-define(wxListCtrl_SetItemColumnImage, 1715).
+-define(wxListCtrl_SetItemPosition, 1716).
+-define(wxListCtrl_SetItemState, 1717).
+-define(wxListCtrl_SetItemText, 1718).
+-define(wxListCtrl_SetItemTextColour, 1719).
+-define(wxListCtrl_SetSingleStyle, 1720).
+-define(wxListCtrl_SetTextColour, 1721).
+-define(wxListCtrl_SetWindowStyleFlag, 1722).
+-define(wxListCtrl_SortItems, 1723).
+-define(wxListCtrl_destroy, 1724).
+-define(wxListView_ClearColumnImage, 1725).
+-define(wxListView_Focus, 1726).
+-define(wxListView_GetFirstSelected, 1727).
+-define(wxListView_GetFocusedItem, 1728).
+-define(wxListView_GetNextSelected, 1729).
+-define(wxListView_IsSelected, 1730).
+-define(wxListView_Select, 1731).
+-define(wxListView_SetColumnImage, 1732).
+-define(wxListItem_new_0, 1733).
+-define(wxListItem_new_1, 1734).
+-define(wxListItem_destruct, 1735).
+-define(wxListItem_Clear, 1736).
+-define(wxListItem_GetAlign, 1737).
+-define(wxListItem_GetBackgroundColour, 1738).
+-define(wxListItem_GetColumn, 1739).
+-define(wxListItem_GetFont, 1740).
+-define(wxListItem_GetId, 1741).
+-define(wxListItem_GetImage, 1742).
+-define(wxListItem_GetMask, 1743).
+-define(wxListItem_GetState, 1744).
+-define(wxListItem_GetText, 1745).
+-define(wxListItem_GetTextColour, 1746).
+-define(wxListItem_GetWidth, 1747).
+-define(wxListItem_SetAlign, 1748).
+-define(wxListItem_SetBackgroundColour, 1749).
+-define(wxListItem_SetColumn, 1750).
+-define(wxListItem_SetFont, 1751).
+-define(wxListItem_SetId, 1752).
+-define(wxListItem_SetImage, 1753).
+-define(wxListItem_SetMask, 1754).
+-define(wxListItem_SetState, 1755).
+-define(wxListItem_SetStateMask, 1756).
+-define(wxListItem_SetText, 1757).
+-define(wxListItem_SetTextColour, 1758).
+-define(wxListItem_SetWidth, 1759).
+-define(wxListItemAttr_new_0, 1760).
+-define(wxListItemAttr_new_3, 1761).
+-define(wxListItemAttr_GetBackgroundColour, 1762).
+-define(wxListItemAttr_GetFont, 1763).
+-define(wxListItemAttr_GetTextColour, 1764).
+-define(wxListItemAttr_HasBackgroundColour, 1765).
+-define(wxListItemAttr_HasFont, 1766).
+-define(wxListItemAttr_HasTextColour, 1767).
+-define(wxListItemAttr_SetBackgroundColour, 1768).
+-define(wxListItemAttr_SetFont, 1769).
+-define(wxListItemAttr_SetTextColour, 1770).
+-define(wxListItemAttr_destroy, 1771).
+-define(wxImageList_new_0, 1772).
+-define(wxImageList_new_3, 1773).
+-define(wxImageList_Add_1, 1774).
+-define(wxImageList_Add_2_0, 1775).
+-define(wxImageList_Add_2_1, 1776).
+-define(wxImageList_Create, 1777).
+-define(wxImageList_Draw, 1779).
+-define(wxImageList_GetBitmap, 1780).
+-define(wxImageList_GetIcon, 1781).
+-define(wxImageList_GetImageCount, 1782).
+-define(wxImageList_GetSize, 1783).
+-define(wxImageList_Remove, 1784).
+-define(wxImageList_RemoveAll, 1785).
+-define(wxImageList_Replace_2, 1786).
+-define(wxImageList_Replace_3, 1787).
+-define(wxImageList_destroy, 1788).
+-define(wxTextAttr_new_0, 1789).
+-define(wxTextAttr_new_2, 1790).
+-define(wxTextAttr_GetAlignment, 1791).
+-define(wxTextAttr_GetBackgroundColour, 1792).
+-define(wxTextAttr_GetFont, 1793).
+-define(wxTextAttr_GetLeftIndent, 1794).
+-define(wxTextAttr_GetLeftSubIndent, 1795).
+-define(wxTextAttr_GetRightIndent, 1796).
+-define(wxTextAttr_GetTabs, 1797).
+-define(wxTextAttr_GetTextColour, 1798).
+-define(wxTextAttr_HasBackgroundColour, 1799).
+-define(wxTextAttr_HasFont, 1800).
+-define(wxTextAttr_HasTextColour, 1801).
+-define(wxTextAttr_GetFlags, 1802).
+-define(wxTextAttr_IsDefault, 1803).
+-define(wxTextAttr_SetAlignment, 1804).
+-define(wxTextAttr_SetBackgroundColour, 1805).
+-define(wxTextAttr_SetFlags, 1806).
+-define(wxTextAttr_SetFont, 1807).
+-define(wxTextAttr_SetLeftIndent, 1808).
+-define(wxTextAttr_SetRightIndent, 1809).
+-define(wxTextAttr_SetTabs, 1810).
+-define(wxTextAttr_SetTextColour, 1811).
+-define(wxTextAttr_destroy, 1812).
+-define(wxTextCtrl_new_3, 1814).
+-define(wxTextCtrl_new_0, 1815).
+-define(wxTextCtrl_destruct, 1817).
+-define(wxTextCtrl_AppendText, 1818).
+-define(wxTextCtrl_CanCopy, 1819).
+-define(wxTextCtrl_CanCut, 1820).
+-define(wxTextCtrl_CanPaste, 1821).
+-define(wxTextCtrl_CanRedo, 1822).
+-define(wxTextCtrl_CanUndo, 1823).
+-define(wxTextCtrl_Clear, 1824).
+-define(wxTextCtrl_Copy, 1825).
+-define(wxTextCtrl_Create, 1826).
+-define(wxTextCtrl_Cut, 1827).
+-define(wxTextCtrl_DiscardEdits, 1828).
+-define(wxTextCtrl_ChangeValue, 1829).
+-define(wxTextCtrl_EmulateKeyPress, 1830).
+-define(wxTextCtrl_GetDefaultStyle, 1831).
+-define(wxTextCtrl_GetInsertionPoint, 1832).
+-define(wxTextCtrl_GetLastPosition, 1833).
+-define(wxTextCtrl_GetLineLength, 1834).
+-define(wxTextCtrl_GetLineText, 1835).
+-define(wxTextCtrl_GetNumberOfLines, 1836).
+-define(wxTextCtrl_GetRange, 1837).
+-define(wxTextCtrl_GetSelection, 1838).
+-define(wxTextCtrl_GetStringSelection, 1839).
+-define(wxTextCtrl_GetStyle, 1840).
+-define(wxTextCtrl_GetValue, 1841).
+-define(wxTextCtrl_IsEditable, 1842).
+-define(wxTextCtrl_IsModified, 1843).
+-define(wxTextCtrl_IsMultiLine, 1844).
+-define(wxTextCtrl_IsSingleLine, 1845).
+-define(wxTextCtrl_LoadFile, 1846).
+-define(wxTextCtrl_MarkDirty, 1847).
+-define(wxTextCtrl_Paste, 1848).
+-define(wxTextCtrl_PositionToXY, 1849).
+-define(wxTextCtrl_Redo, 1850).
+-define(wxTextCtrl_Remove, 1851).
+-define(wxTextCtrl_Replace, 1852).
+-define(wxTextCtrl_SaveFile, 1853).
+-define(wxTextCtrl_SetDefaultStyle, 1854).
+-define(wxTextCtrl_SetEditable, 1855).
+-define(wxTextCtrl_SetInsertionPoint, 1856).
+-define(wxTextCtrl_SetInsertionPointEnd, 1857).
+-define(wxTextCtrl_SetMaxLength, 1859).
+-define(wxTextCtrl_SetSelection, 1860).
+-define(wxTextCtrl_SetStyle, 1861).
+-define(wxTextCtrl_SetValue, 1862).
+-define(wxTextCtrl_ShowPosition, 1863).
+-define(wxTextCtrl_Undo, 1864).
+-define(wxTextCtrl_WriteText, 1865).
+-define(wxTextCtrl_XYToPosition, 1866).
+-define(wxNotebook_new_0, 1869).
+-define(wxNotebook_new_3, 1870).
+-define(wxNotebook_destruct, 1871).
+-define(wxNotebook_AddPage, 1872).
+-define(wxNotebook_AdvanceSelection, 1873).
+-define(wxNotebook_AssignImageList, 1874).
+-define(wxNotebook_Create, 1875).
+-define(wxNotebook_DeleteAllPages, 1876).
+-define(wxNotebook_DeletePage, 1877).
+-define(wxNotebook_RemovePage, 1878).
+-define(wxNotebook_GetCurrentPage, 1879).
+-define(wxNotebook_GetImageList, 1880).
+-define(wxNotebook_GetPage, 1882).
+-define(wxNotebook_GetPageCount, 1883).
+-define(wxNotebook_GetPageImage, 1884).
+-define(wxNotebook_GetPageText, 1885).
+-define(wxNotebook_GetRowCount, 1886).
+-define(wxNotebook_GetSelection, 1887).
+-define(wxNotebook_GetThemeBackgroundColour, 1888).
+-define(wxNotebook_HitTest, 1890).
+-define(wxNotebook_InsertPage, 1892).
+-define(wxNotebook_SetImageList, 1893).
+-define(wxNotebook_SetPadding, 1894).
+-define(wxNotebook_SetPageSize, 1895).
+-define(wxNotebook_SetPageImage, 1896).
+-define(wxNotebook_SetPageText, 1897).
+-define(wxNotebook_SetSelection, 1898).
+-define(wxNotebook_ChangeSelection, 1899).
+-define(wxChoicebook_new_0, 1900).
+-define(wxChoicebook_new_3, 1901).
+-define(wxChoicebook_AddPage, 1902).
+-define(wxChoicebook_AdvanceSelection, 1903).
+-define(wxChoicebook_AssignImageList, 1904).
+-define(wxChoicebook_Create, 1905).
+-define(wxChoicebook_DeleteAllPages, 1906).
+-define(wxChoicebook_DeletePage, 1907).
+-define(wxChoicebook_RemovePage, 1908).
+-define(wxChoicebook_GetCurrentPage, 1909).
+-define(wxChoicebook_GetImageList, 1910).
+-define(wxChoicebook_GetPage, 1912).
+-define(wxChoicebook_GetPageCount, 1913).
+-define(wxChoicebook_GetPageImage, 1914).
+-define(wxChoicebook_GetPageText, 1915).
+-define(wxChoicebook_GetSelection, 1916).
+-define(wxChoicebook_HitTest, 1917).
+-define(wxChoicebook_InsertPage, 1918).
+-define(wxChoicebook_SetImageList, 1919).
+-define(wxChoicebook_SetPageSize, 1920).
+-define(wxChoicebook_SetPageImage, 1921).
+-define(wxChoicebook_SetPageText, 1922).
+-define(wxChoicebook_SetSelection, 1923).
+-define(wxChoicebook_ChangeSelection, 1924).
+-define(wxChoicebook_destroy, 1925).
+-define(wxToolbook_new_0, 1926).
+-define(wxToolbook_new_3, 1927).
+-define(wxToolbook_AddPage, 1928).
+-define(wxToolbook_AdvanceSelection, 1929).
+-define(wxToolbook_AssignImageList, 1930).
+-define(wxToolbook_Create, 1931).
+-define(wxToolbook_DeleteAllPages, 1932).
+-define(wxToolbook_DeletePage, 1933).
+-define(wxToolbook_RemovePage, 1934).
+-define(wxToolbook_GetCurrentPage, 1935).
+-define(wxToolbook_GetImageList, 1936).
+-define(wxToolbook_GetPage, 1938).
+-define(wxToolbook_GetPageCount, 1939).
+-define(wxToolbook_GetPageImage, 1940).
+-define(wxToolbook_GetPageText, 1941).
+-define(wxToolbook_GetSelection, 1942).
+-define(wxToolbook_HitTest, 1944).
+-define(wxToolbook_InsertPage, 1945).
+-define(wxToolbook_SetImageList, 1946).
+-define(wxToolbook_SetPageSize, 1947).
+-define(wxToolbook_SetPageImage, 1948).
+-define(wxToolbook_SetPageText, 1949).
+-define(wxToolbook_SetSelection, 1950).
+-define(wxToolbook_ChangeSelection, 1951).
+-define(wxToolbook_destroy, 1952).
+-define(wxListbook_new_0, 1953).
+-define(wxListbook_new_3, 1954).
+-define(wxListbook_AddPage, 1955).
+-define(wxListbook_AdvanceSelection, 1956).
+-define(wxListbook_AssignImageList, 1957).
+-define(wxListbook_Create, 1958).
+-define(wxListbook_DeleteAllPages, 1959).
+-define(wxListbook_DeletePage, 1960).
+-define(wxListbook_RemovePage, 1961).
+-define(wxListbook_GetCurrentPage, 1962).
+-define(wxListbook_GetImageList, 1963).
+-define(wxListbook_GetPage, 1965).
+-define(wxListbook_GetPageCount, 1966).
+-define(wxListbook_GetPageImage, 1967).
+-define(wxListbook_GetPageText, 1968).
+-define(wxListbook_GetSelection, 1969).
+-define(wxListbook_HitTest, 1971).
+-define(wxListbook_InsertPage, 1972).
+-define(wxListbook_SetImageList, 1973).
+-define(wxListbook_SetPageSize, 1974).
+-define(wxListbook_SetPageImage, 1975).
+-define(wxListbook_SetPageText, 1976).
+-define(wxListbook_SetSelection, 1977).
+-define(wxListbook_ChangeSelection, 1978).
+-define(wxListbook_destroy, 1979).
+-define(wxTreebook_new_0, 1980).
+-define(wxTreebook_new_3, 1981).
+-define(wxTreebook_AddPage, 1982).
+-define(wxTreebook_AdvanceSelection, 1983).
+-define(wxTreebook_AssignImageList, 1984).
+-define(wxTreebook_Create, 1985).
+-define(wxTreebook_DeleteAllPages, 1986).
+-define(wxTreebook_DeletePage, 1987).
+-define(wxTreebook_RemovePage, 1988).
+-define(wxTreebook_GetCurrentPage, 1989).
+-define(wxTreebook_GetImageList, 1990).
+-define(wxTreebook_GetPage, 1992).
+-define(wxTreebook_GetPageCount, 1993).
+-define(wxTreebook_GetPageImage, 1994).
+-define(wxTreebook_GetPageText, 1995).
+-define(wxTreebook_GetSelection, 1996).
+-define(wxTreebook_ExpandNode, 1997).
+-define(wxTreebook_IsNodeExpanded, 1998).
+-define(wxTreebook_HitTest, 2000).
+-define(wxTreebook_InsertPage, 2001).
+-define(wxTreebook_InsertSubPage, 2002).
+-define(wxTreebook_SetImageList, 2003).
+-define(wxTreebook_SetPageSize, 2004).
+-define(wxTreebook_SetPageImage, 2005).
+-define(wxTreebook_SetPageText, 2006).
+-define(wxTreebook_SetSelection, 2007).
+-define(wxTreebook_ChangeSelection, 2008).
+-define(wxTreebook_destroy, 2009).
+-define(wxTreeCtrl_new_2, 2012).
+-define(wxTreeCtrl_new_0, 2013).
+-define(wxTreeCtrl_destruct, 2015).
+-define(wxTreeCtrl_AddRoot, 2016).
+-define(wxTreeCtrl_AppendItem, 2017).
+-define(wxTreeCtrl_AssignImageList, 2018).
+-define(wxTreeCtrl_AssignStateImageList, 2019).
+-define(wxTreeCtrl_Collapse, 2020).
+-define(wxTreeCtrl_CollapseAndReset, 2021).
+-define(wxTreeCtrl_Create, 2022).
+-define(wxTreeCtrl_Delete, 2023).
+-define(wxTreeCtrl_DeleteAllItems, 2024).
+-define(wxTreeCtrl_DeleteChildren, 2025).
+-define(wxTreeCtrl_EditLabel, 2026).
+-define(wxTreeCtrl_EnsureVisible, 2027).
+-define(wxTreeCtrl_Expand, 2028).
+-define(wxTreeCtrl_GetBoundingRect, 2029).
+-define(wxTreeCtrl_GetChildrenCount, 2031).
+-define(wxTreeCtrl_GetCount, 2032).
+-define(wxTreeCtrl_GetEditControl, 2033).
+-define(wxTreeCtrl_GetFirstChild, 2034).
+-define(wxTreeCtrl_GetNextChild, 2035).
+-define(wxTreeCtrl_GetFirstVisibleItem, 2036).
+-define(wxTreeCtrl_GetImageList, 2037).
+-define(wxTreeCtrl_GetIndent, 2038).
+-define(wxTreeCtrl_GetItemBackgroundColour, 2039).
+-define(wxTreeCtrl_GetItemData, 2040).
+-define(wxTreeCtrl_GetItemFont, 2041).
+-define(wxTreeCtrl_GetItemImage_1, 2042).
+-define(wxTreeCtrl_GetItemImage_2, 2043).
+-define(wxTreeCtrl_GetItemText, 2044).
+-define(wxTreeCtrl_GetItemTextColour, 2045).
+-define(wxTreeCtrl_GetLastChild, 2046).
+-define(wxTreeCtrl_GetNextSibling, 2047).
+-define(wxTreeCtrl_GetNextVisible, 2048).
+-define(wxTreeCtrl_GetItemParent, 2049).
+-define(wxTreeCtrl_GetPrevSibling, 2050).
+-define(wxTreeCtrl_GetPrevVisible, 2051).
+-define(wxTreeCtrl_GetRootItem, 2052).
+-define(wxTreeCtrl_GetSelection, 2053).
+-define(wxTreeCtrl_GetSelections, 2054).
+-define(wxTreeCtrl_GetStateImageList, 2055).
+-define(wxTreeCtrl_HitTest, 2056).
+-define(wxTreeCtrl_InsertItem, 2058).
+-define(wxTreeCtrl_IsBold, 2059).
+-define(wxTreeCtrl_IsExpanded, 2060).
+-define(wxTreeCtrl_IsSelected, 2061).
+-define(wxTreeCtrl_IsVisible, 2062).
+-define(wxTreeCtrl_ItemHasChildren, 2063).
+-define(wxTreeCtrl_IsTreeItemIdOk, 2064).
+-define(wxTreeCtrl_PrependItem, 2065).
+-define(wxTreeCtrl_ScrollTo, 2066).
+-define(wxTreeCtrl_SelectItem_1, 2067).
+-define(wxTreeCtrl_SelectItem_2, 2068).
+-define(wxTreeCtrl_SetIndent, 2069).
+-define(wxTreeCtrl_SetImageList, 2070).
+-define(wxTreeCtrl_SetItemBackgroundColour, 2071).
+-define(wxTreeCtrl_SetItemBold, 2072).
+-define(wxTreeCtrl_SetItemData, 2073).
+-define(wxTreeCtrl_SetItemDropHighlight, 2074).
+-define(wxTreeCtrl_SetItemFont, 2075).
+-define(wxTreeCtrl_SetItemHasChildren, 2076).
+-define(wxTreeCtrl_SetItemImage_2, 2077).
+-define(wxTreeCtrl_SetItemImage_3, 2078).
+-define(wxTreeCtrl_SetItemText, 2079).
+-define(wxTreeCtrl_SetItemTextColour, 2080).
+-define(wxTreeCtrl_SetStateImageList, 2081).
+-define(wxTreeCtrl_SetWindowStyle, 2082).
+-define(wxTreeCtrl_SortChildren, 2083).
+-define(wxTreeCtrl_Toggle, 2084).
+-define(wxTreeCtrl_ToggleItemSelection, 2085).
+-define(wxTreeCtrl_Unselect, 2086).
+-define(wxTreeCtrl_UnselectAll, 2087).
+-define(wxTreeCtrl_UnselectItem, 2088).
+-define(wxScrollBar_new_0, 2089).
+-define(wxScrollBar_new_3, 2090).
+-define(wxScrollBar_destruct, 2091).
+-define(wxScrollBar_Create, 2092).
+-define(wxScrollBar_GetRange, 2093).
+-define(wxScrollBar_GetPageSize, 2094).
+-define(wxScrollBar_GetThumbPosition, 2095).
+-define(wxScrollBar_GetThumbSize, 2096).
+-define(wxScrollBar_SetThumbPosition, 2097).
+-define(wxScrollBar_SetScrollbar, 2098).
+-define(wxSpinButton_new_2, 2100).
+-define(wxSpinButton_new_0, 2101).
+-define(wxSpinButton_Create, 2102).
+-define(wxSpinButton_GetMax, 2103).
+-define(wxSpinButton_GetMin, 2104).
+-define(wxSpinButton_GetValue, 2105).
+-define(wxSpinButton_SetRange, 2106).
+-define(wxSpinButton_SetValue, 2107).
+-define(wxSpinButton_destroy, 2108).
+-define(wxSpinCtrl_new_0, 2109).
+-define(wxSpinCtrl_new_2, 2110).
+-define(wxSpinCtrl_Create, 2112).
+-define(wxSpinCtrl_SetValue_1_1, 2115).
+-define(wxSpinCtrl_SetValue_1_0, 2116).
+-define(wxSpinCtrl_GetValue, 2118).
+-define(wxSpinCtrl_SetRange, 2120).
+-define(wxSpinCtrl_SetSelection, 2121).
+-define(wxSpinCtrl_GetMin, 2123).
+-define(wxSpinCtrl_GetMax, 2125).
+-define(wxSpinCtrl_destroy, 2126).
+-define(wxStaticText_new_0, 2127).
+-define(wxStaticText_new_4, 2128).
+-define(wxStaticText_Create, 2129).
+-define(wxStaticText_GetLabel, 2130).
+-define(wxStaticText_SetLabel, 2131).
+-define(wxStaticText_Wrap, 2132).
+-define(wxStaticText_destroy, 2133).
+-define(wxStaticBitmap_new_0, 2134).
+-define(wxStaticBitmap_new_4, 2135).
+-define(wxStaticBitmap_Create, 2136).
+-define(wxStaticBitmap_GetBitmap, 2137).
+-define(wxStaticBitmap_SetBitmap, 2138).
+-define(wxStaticBitmap_destroy, 2139).
+-define(wxRadioBox_new, 2140).
+-define(wxRadioBox_destruct, 2142).
+-define(wxRadioBox_Create, 2143).
+-define(wxRadioBox_Enable_2, 2144).
+-define(wxRadioBox_Enable_1, 2145).
+-define(wxRadioBox_GetSelection, 2146).
+-define(wxRadioBox_GetString, 2147).
+-define(wxRadioBox_SetSelection, 2148).
+-define(wxRadioBox_Show_2, 2149).
+-define(wxRadioBox_Show_1, 2150).
+-define(wxRadioBox_GetColumnCount, 2151).
+-define(wxRadioBox_GetItemHelpText, 2152).
+-define(wxRadioBox_GetItemToolTip, 2153).
+-define(wxRadioBox_GetItemFromPoint, 2155).
+-define(wxRadioBox_GetRowCount, 2156).
+-define(wxRadioBox_IsItemEnabled, 2157).
+-define(wxRadioBox_IsItemShown, 2158).
+-define(wxRadioBox_SetItemHelpText, 2159).
+-define(wxRadioBox_SetItemToolTip, 2160).
+-define(wxRadioButton_new_0, 2161).
+-define(wxRadioButton_new_4, 2162).
+-define(wxRadioButton_Create, 2163).
+-define(wxRadioButton_GetValue, 2164).
+-define(wxRadioButton_SetValue, 2165).
+-define(wxRadioButton_destroy, 2166).
+-define(wxSlider_new_6, 2168).
+-define(wxSlider_new_0, 2169).
+-define(wxSlider_Create, 2170).
+-define(wxSlider_GetLineSize, 2171).
+-define(wxSlider_GetMax, 2172).
+-define(wxSlider_GetMin, 2173).
+-define(wxSlider_GetPageSize, 2174).
+-define(wxSlider_GetThumbLength, 2175).
+-define(wxSlider_GetValue, 2176).
+-define(wxSlider_SetLineSize, 2177).
+-define(wxSlider_SetPageSize, 2178).
+-define(wxSlider_SetRange, 2179).
+-define(wxSlider_SetThumbLength, 2180).
+-define(wxSlider_SetValue, 2181).
+-define(wxSlider_destroy, 2182).
+-define(wxDialog_new_4, 2184).
+-define(wxDialog_new_0, 2185).
+-define(wxDialog_destruct, 2187).
+-define(wxDialog_Create, 2188).
+-define(wxDialog_CreateButtonSizer, 2189).
+-define(wxDialog_CreateStdDialogButtonSizer, 2190).
+-define(wxDialog_EndModal, 2191).
+-define(wxDialog_GetAffirmativeId, 2192).
+-define(wxDialog_GetReturnCode, 2193).
+-define(wxDialog_IsModal, 2194).
+-define(wxDialog_SetAffirmativeId, 2195).
+-define(wxDialog_SetReturnCode, 2196).
+-define(wxDialog_Show, 2197).
+-define(wxDialog_ShowModal, 2198).
+-define(wxColourDialog_new_0, 2199).
+-define(wxColourDialog_new_2, 2200).
+-define(wxColourDialog_destruct, 2201).
+-define(wxColourDialog_Create, 2202).
+-define(wxColourDialog_GetColourData, 2203).
+-define(wxColourData_new_0, 2204).
+-define(wxColourData_new_1, 2205).
+-define(wxColourData_destruct, 2206).
+-define(wxColourData_GetChooseFull, 2207).
+-define(wxColourData_GetColour, 2208).
+-define(wxColourData_GetCustomColour, 2210).
+-define(wxColourData_SetChooseFull, 2211).
+-define(wxColourData_SetColour, 2212).
+-define(wxColourData_SetCustomColour, 2213).
+-define(wxPalette_new_0, 2214).
+-define(wxPalette_new_4, 2215).
+-define(wxPalette_destruct, 2217).
+-define(wxPalette_Create, 2218).
+-define(wxPalette_GetColoursCount, 2219).
+-define(wxPalette_GetPixel, 2220).
+-define(wxPalette_GetRGB, 2221).
+-define(wxPalette_IsOk, 2222).
+-define(wxDirDialog_new, 2226).
+-define(wxDirDialog_destruct, 2227).
+-define(wxDirDialog_GetPath, 2228).
+-define(wxDirDialog_GetMessage, 2229).
+-define(wxDirDialog_SetMessage, 2230).
+-define(wxDirDialog_SetPath, 2231).
+-define(wxFileDialog_new, 2235).
+-define(wxFileDialog_destruct, 2236).
+-define(wxFileDialog_GetDirectory, 2237).
+-define(wxFileDialog_GetFilename, 2238).
+-define(wxFileDialog_GetFilenames, 2239).
+-define(wxFileDialog_GetFilterIndex, 2240).
+-define(wxFileDialog_GetMessage, 2241).
+-define(wxFileDialog_GetPath, 2242).
+-define(wxFileDialog_GetPaths, 2243).
+-define(wxFileDialog_GetWildcard, 2244).
+-define(wxFileDialog_SetDirectory, 2245).
+-define(wxFileDialog_SetFilename, 2246).
+-define(wxFileDialog_SetFilterIndex, 2247).
+-define(wxFileDialog_SetMessage, 2248).
+-define(wxFileDialog_SetPath, 2249).
+-define(wxFileDialog_SetWildcard, 2250).
+-define(wxPickerBase_SetInternalMargin, 2251).
+-define(wxPickerBase_GetInternalMargin, 2252).
+-define(wxPickerBase_SetTextCtrlProportion, 2253).
+-define(wxPickerBase_SetPickerCtrlProportion, 2254).
+-define(wxPickerBase_GetTextCtrlProportion, 2255).
+-define(wxPickerBase_GetPickerCtrlProportion, 2256).
+-define(wxPickerBase_HasTextCtrl, 2257).
+-define(wxPickerBase_GetTextCtrl, 2258).
+-define(wxPickerBase_IsTextCtrlGrowable, 2259).
+-define(wxPickerBase_SetPickerCtrlGrowable, 2260).
+-define(wxPickerBase_SetTextCtrlGrowable, 2261).
+-define(wxPickerBase_IsPickerCtrlGrowable, 2262).
+-define(wxFilePickerCtrl_new_0, 2263).
+-define(wxFilePickerCtrl_new_3, 2264).
+-define(wxFilePickerCtrl_Create, 2265).
+-define(wxFilePickerCtrl_GetPath, 2266).
+-define(wxFilePickerCtrl_SetPath, 2267).
+-define(wxFilePickerCtrl_destroy, 2268).
+-define(wxDirPickerCtrl_new_0, 2269).
+-define(wxDirPickerCtrl_new_3, 2270).
+-define(wxDirPickerCtrl_Create, 2271).
+-define(wxDirPickerCtrl_GetPath, 2272).
+-define(wxDirPickerCtrl_SetPath, 2273).
+-define(wxDirPickerCtrl_destroy, 2274).
+-define(wxColourPickerCtrl_new_0, 2275).
+-define(wxColourPickerCtrl_new_3, 2276).
+-define(wxColourPickerCtrl_Create, 2277).
+-define(wxColourPickerCtrl_GetColour, 2278).
+-define(wxColourPickerCtrl_SetColour_1_1, 2279).
+-define(wxColourPickerCtrl_SetColour_1_0, 2280).
+-define(wxColourPickerCtrl_destroy, 2281).
+-define(wxDatePickerCtrl_new_0, 2282).
+-define(wxDatePickerCtrl_new_3, 2283).
+-define(wxDatePickerCtrl_GetRange, 2284).
+-define(wxDatePickerCtrl_GetValue, 2285).
+-define(wxDatePickerCtrl_SetRange, 2286).
+-define(wxDatePickerCtrl_SetValue, 2287).
+-define(wxDatePickerCtrl_destroy, 2288).
+-define(wxFontPickerCtrl_new_0, 2289).
+-define(wxFontPickerCtrl_new_3, 2290).
+-define(wxFontPickerCtrl_Create, 2291).
+-define(wxFontPickerCtrl_GetSelectedFont, 2292).
+-define(wxFontPickerCtrl_SetSelectedFont, 2293).
+-define(wxFontPickerCtrl_GetMaxPointSize, 2294).
+-define(wxFontPickerCtrl_SetMaxPointSize, 2295).
+-define(wxFontPickerCtrl_destroy, 2296).
+-define(wxFindReplaceDialog_new_0, 2299).
+-define(wxFindReplaceDialog_new_4, 2300).
+-define(wxFindReplaceDialog_destruct, 2301).
+-define(wxFindReplaceDialog_Create, 2302).
+-define(wxFindReplaceDialog_GetData, 2303).
+-define(wxFindReplaceData_new_0, 2304).
+-define(wxFindReplaceData_new_1, 2305).
+-define(wxFindReplaceData_GetFindString, 2306).
+-define(wxFindReplaceData_GetReplaceString, 2307).
+-define(wxFindReplaceData_GetFlags, 2308).
+-define(wxFindReplaceData_SetFlags, 2309).
+-define(wxFindReplaceData_SetFindString, 2310).
+-define(wxFindReplaceData_SetReplaceString, 2311).
+-define(wxFindReplaceData_destroy, 2312).
+-define(wxMultiChoiceDialog_new_0, 2313).
+-define(wxMultiChoiceDialog_new_5, 2315).
+-define(wxMultiChoiceDialog_GetSelections, 2316).
+-define(wxMultiChoiceDialog_SetSelections, 2317).
+-define(wxMultiChoiceDialog_destroy, 2318).
+-define(wxSingleChoiceDialog_new_0, 2319).
+-define(wxSingleChoiceDialog_new_5, 2321).
+-define(wxSingleChoiceDialog_GetSelection, 2322).
+-define(wxSingleChoiceDialog_GetStringSelection, 2323).
+-define(wxSingleChoiceDialog_SetSelection, 2324).
+-define(wxSingleChoiceDialog_destroy, 2325).
+-define(wxTextEntryDialog_new, 2326).
+-define(wxTextEntryDialog_GetValue, 2327).
+-define(wxTextEntryDialog_SetValue, 2328).
+-define(wxTextEntryDialog_destroy, 2329).
+-define(wxPasswordEntryDialog_new, 2330).
+-define(wxPasswordEntryDialog_destroy, 2331).
+-define(wxFontData_new_0, 2332).
+-define(wxFontData_new_1, 2333).
+-define(wxFontData_destruct, 2334).
+-define(wxFontData_EnableEffects, 2335).
+-define(wxFontData_GetAllowSymbols, 2336).
+-define(wxFontData_GetColour, 2337).
+-define(wxFontData_GetChosenFont, 2338).
+-define(wxFontData_GetEnableEffects, 2339).
+-define(wxFontData_GetInitialFont, 2340).
+-define(wxFontData_GetShowHelp, 2341).
+-define(wxFontData_SetAllowSymbols, 2342).
+-define(wxFontData_SetChosenFont, 2343).
+-define(wxFontData_SetColour, 2344).
+-define(wxFontData_SetInitialFont, 2345).
+-define(wxFontData_SetRange, 2346).
+-define(wxFontData_SetShowHelp, 2347).
+-define(wxFontDialog_new_0, 2351).
+-define(wxFontDialog_new_2, 2353).
+-define(wxFontDialog_Create, 2355).
+-define(wxFontDialog_GetFontData, 2356).
+-define(wxFontDialog_destroy, 2358).
+-define(wxProgressDialog_new, 2359).
+-define(wxProgressDialog_destruct, 2360).
+-define(wxProgressDialog_Resume, 2361).
+-define(wxProgressDialog_Update_2, 2362).
+-define(wxProgressDialog_Update_0, 2363).
+-define(wxMessageDialog_new, 2364).
+-define(wxMessageDialog_destruct, 2365).
+-define(wxPageSetupDialog_new, 2366).
+-define(wxPageSetupDialog_destruct, 2367).
+-define(wxPageSetupDialog_GetPageSetupData, 2368).
+-define(wxPageSetupDialog_ShowModal, 2369).
+-define(wxPageSetupDialogData_new_0, 2370).
+-define(wxPageSetupDialogData_new_1_0, 2371).
+-define(wxPageSetupDialogData_new_1_1, 2372).
+-define(wxPageSetupDialogData_destruct, 2373).
+-define(wxPageSetupDialogData_EnableHelp, 2374).
+-define(wxPageSetupDialogData_EnableMargins, 2375).
+-define(wxPageSetupDialogData_EnableOrientation, 2376).
+-define(wxPageSetupDialogData_EnablePaper, 2377).
+-define(wxPageSetupDialogData_EnablePrinter, 2378).
+-define(wxPageSetupDialogData_GetDefaultMinMargins, 2379).
+-define(wxPageSetupDialogData_GetEnableMargins, 2380).
+-define(wxPageSetupDialogData_GetEnableOrientation, 2381).
+-define(wxPageSetupDialogData_GetEnablePaper, 2382).
+-define(wxPageSetupDialogData_GetEnablePrinter, 2383).
+-define(wxPageSetupDialogData_GetEnableHelp, 2384).
+-define(wxPageSetupDialogData_GetDefaultInfo, 2385).
+-define(wxPageSetupDialogData_GetMarginTopLeft, 2386).
+-define(wxPageSetupDialogData_GetMarginBottomRight, 2387).
+-define(wxPageSetupDialogData_GetMinMarginTopLeft, 2388).
+-define(wxPageSetupDialogData_GetMinMarginBottomRight, 2389).
+-define(wxPageSetupDialogData_GetPaperId, 2390).
+-define(wxPageSetupDialogData_GetPaperSize, 2391).
+-define(wxPageSetupDialogData_GetPrintData, 2393).
+-define(wxPageSetupDialogData_IsOk, 2394).
+-define(wxPageSetupDialogData_SetDefaultInfo, 2395).
+-define(wxPageSetupDialogData_SetDefaultMinMargins, 2396).
+-define(wxPageSetupDialogData_SetMarginTopLeft, 2397).
+-define(wxPageSetupDialogData_SetMarginBottomRight, 2398).
+-define(wxPageSetupDialogData_SetMinMarginTopLeft, 2399).
+-define(wxPageSetupDialogData_SetMinMarginBottomRight, 2400).
+-define(wxPageSetupDialogData_SetPaperId, 2401).
+-define(wxPageSetupDialogData_SetPaperSize_1_1, 2402).
+-define(wxPageSetupDialogData_SetPaperSize_1_0, 2403).
+-define(wxPageSetupDialogData_SetPrintData, 2404).
+-define(wxPrintDialog_new_2_0, 2405).
+-define(wxPrintDialog_new_2_1, 2406).
+-define(wxPrintDialog_destruct, 2407).
+-define(wxPrintDialog_GetPrintDialogData, 2408).
+-define(wxPrintDialog_GetPrintDC, 2409).
+-define(wxPrintDialogData_new_0, 2410).
+-define(wxPrintDialogData_new_1_1, 2411).
+-define(wxPrintDialogData_new_1_0, 2412).
+-define(wxPrintDialogData_destruct, 2413).
+-define(wxPrintDialogData_EnableHelp, 2414).
+-define(wxPrintDialogData_EnablePageNumbers, 2415).
+-define(wxPrintDialogData_EnablePrintToFile, 2416).
+-define(wxPrintDialogData_EnableSelection, 2417).
+-define(wxPrintDialogData_GetAllPages, 2418).
+-define(wxPrintDialogData_GetCollate, 2419).
+-define(wxPrintDialogData_GetFromPage, 2420).
+-define(wxPrintDialogData_GetMaxPage, 2421).
+-define(wxPrintDialogData_GetMinPage, 2422).
+-define(wxPrintDialogData_GetNoCopies, 2423).
+-define(wxPrintDialogData_GetPrintData, 2424).
+-define(wxPrintDialogData_GetPrintToFile, 2425).
+-define(wxPrintDialogData_GetSelection, 2426).
+-define(wxPrintDialogData_GetToPage, 2427).
+-define(wxPrintDialogData_IsOk, 2428).
+-define(wxPrintDialogData_SetCollate, 2429).
+-define(wxPrintDialogData_SetFromPage, 2430).
+-define(wxPrintDialogData_SetMaxPage, 2431).
+-define(wxPrintDialogData_SetMinPage, 2432).
+-define(wxPrintDialogData_SetNoCopies, 2433).
+-define(wxPrintDialogData_SetPrintData, 2434).
+-define(wxPrintDialogData_SetPrintToFile, 2435).
+-define(wxPrintDialogData_SetSelection, 2436).
+-define(wxPrintDialogData_SetToPage, 2437).
+-define(wxPrintData_new_0, 2438).
+-define(wxPrintData_new_1, 2439).
+-define(wxPrintData_destruct, 2440).
+-define(wxPrintData_GetCollate, 2441).
+-define(wxPrintData_GetBin, 2442).
+-define(wxPrintData_GetColour, 2443).
+-define(wxPrintData_GetDuplex, 2444).
+-define(wxPrintData_GetNoCopies, 2445).
+-define(wxPrintData_GetOrientation, 2446).
+-define(wxPrintData_GetPaperId, 2447).
+-define(wxPrintData_GetPrinterName, 2448).
+-define(wxPrintData_GetQuality, 2449).
+-define(wxPrintData_IsOk, 2450).
+-define(wxPrintData_SetBin, 2451).
+-define(wxPrintData_SetCollate, 2452).
+-define(wxPrintData_SetColour, 2453).
+-define(wxPrintData_SetDuplex, 2454).
+-define(wxPrintData_SetNoCopies, 2455).
+-define(wxPrintData_SetOrientation, 2456).
+-define(wxPrintData_SetPaperId, 2457).
+-define(wxPrintData_SetPrinterName, 2458).
+-define(wxPrintData_SetQuality, 2459).
+-define(wxPrintPreview_new_2, 2462).
+-define(wxPrintPreview_new_3, 2463).
+-define(wxPrintPreview_destruct, 2465).
+-define(wxPrintPreview_GetCanvas, 2466).
+-define(wxPrintPreview_GetCurrentPage, 2467).
+-define(wxPrintPreview_GetFrame, 2468).
+-define(wxPrintPreview_GetMaxPage, 2469).
+-define(wxPrintPreview_GetMinPage, 2470).
+-define(wxPrintPreview_GetPrintout, 2471).
+-define(wxPrintPreview_GetPrintoutForPrinting, 2472).
+-define(wxPrintPreview_IsOk, 2473).
+-define(wxPrintPreview_PaintPage, 2474).
+-define(wxPrintPreview_Print, 2475).
+-define(wxPrintPreview_RenderPage, 2476).
+-define(wxPrintPreview_SetCanvas, 2477).
+-define(wxPrintPreview_SetCurrentPage, 2478).
+-define(wxPrintPreview_SetFrame, 2479).
+-define(wxPrintPreview_SetPrintout, 2480).
+-define(wxPrintPreview_SetZoom, 2481).
+-define(wxPreviewFrame_new, 2482).
+-define(wxPreviewFrame_destruct, 2483).
+-define(wxPreviewFrame_CreateControlBar, 2484).
+-define(wxPreviewFrame_CreateCanvas, 2485).
+-define(wxPreviewFrame_Initialize, 2486).
+-define(wxPreviewFrame_OnCloseWindow, 2487).
+-define(wxPreviewControlBar_new, 2488).
+-define(wxPreviewControlBar_destruct, 2489).
+-define(wxPreviewControlBar_CreateButtons, 2490).
+-define(wxPreviewControlBar_GetPrintPreview, 2491).
+-define(wxPreviewControlBar_GetZoomControl, 2492).
+-define(wxPreviewControlBar_SetZoomControl, 2493).
+-define(wxPrinter_new, 2495).
+-define(wxPrinter_CreateAbortWindow, 2496).
+-define(wxPrinter_GetAbort, 2497).
+-define(wxPrinter_GetLastError, 2498).
+-define(wxPrinter_GetPrintDialogData, 2499).
+-define(wxPrinter_Print, 2500).
+-define(wxPrinter_PrintDialog, 2501).
+-define(wxPrinter_ReportError, 2502).
+-define(wxPrinter_Setup, 2503).
+-define(wxPrinter_destroy, 2504).
+-define(wxXmlResource_new_1, 2505).
+-define(wxXmlResource_new_2, 2506).
+-define(wxXmlResource_destruct, 2507).
+-define(wxXmlResource_AttachUnknownControl, 2508).
+-define(wxXmlResource_ClearHandlers, 2509).
+-define(wxXmlResource_CompareVersion, 2510).
+-define(wxXmlResource_Get, 2511).
+-define(wxXmlResource_GetFlags, 2512).
+-define(wxXmlResource_GetVersion, 2513).
+-define(wxXmlResource_GetXRCID, 2514).
+-define(wxXmlResource_InitAllHandlers, 2515).
+-define(wxXmlResource_Load, 2516).
+-define(wxXmlResource_LoadBitmap, 2517).
+-define(wxXmlResource_LoadDialog_2, 2518).
+-define(wxXmlResource_LoadDialog_3, 2519).
+-define(wxXmlResource_LoadFrame_2, 2520).
+-define(wxXmlResource_LoadFrame_3, 2521).
+-define(wxXmlResource_LoadIcon, 2522).
+-define(wxXmlResource_LoadMenu, 2523).
+-define(wxXmlResource_LoadMenuBar_2, 2524).
+-define(wxXmlResource_LoadMenuBar_1, 2525).
+-define(wxXmlResource_LoadPanel_2, 2526).
+-define(wxXmlResource_LoadPanel_3, 2527).
+-define(wxXmlResource_LoadToolBar, 2528).
+-define(wxXmlResource_Set, 2529).
+-define(wxXmlResource_SetFlags, 2530).
+-define(wxXmlResource_Unload, 2531).
+-define(wxXmlResource_xrcctrl, 2532).
+-define(wxHtmlEasyPrinting_new, 2533).
+-define(wxHtmlEasyPrinting_destruct, 2534).
+-define(wxHtmlEasyPrinting_GetPrintData, 2535).
+-define(wxHtmlEasyPrinting_GetPageSetupData, 2536).
+-define(wxHtmlEasyPrinting_PreviewFile, 2537).
+-define(wxHtmlEasyPrinting_PreviewText, 2538).
+-define(wxHtmlEasyPrinting_PrintFile, 2539).
+-define(wxHtmlEasyPrinting_PrintText, 2540).
+-define(wxHtmlEasyPrinting_PageSetup, 2541).
+-define(wxHtmlEasyPrinting_SetFonts, 2542).
+-define(wxHtmlEasyPrinting_SetHeader, 2543).
+-define(wxHtmlEasyPrinting_SetFooter, 2544).
+-define(wxGLCanvas_new_2, 2546).
+-define(wxGLCanvas_new_3_1, 2547).
+-define(wxGLCanvas_new_3_0, 2548).
+-define(wxGLCanvas_GetContext, 2549).
+-define(wxGLCanvas_SetCurrent, 2551).
+-define(wxGLCanvas_SwapBuffers, 2552).
+-define(wxGLCanvas_destroy, 2553).
+-define(wxAuiManager_new, 2554).
+-define(wxAuiManager_destruct, 2555).
+-define(wxAuiManager_AddPane_2_1, 2556).
+-define(wxAuiManager_AddPane_3, 2557).
+-define(wxAuiManager_AddPane_2_0, 2558).
+-define(wxAuiManager_DetachPane, 2559).
+-define(wxAuiManager_GetAllPanes, 2560).
+-define(wxAuiManager_GetArtProvider, 2561).
+-define(wxAuiManager_GetDockSizeConstraint, 2562).
+-define(wxAuiManager_GetFlags, 2563).
+-define(wxAuiManager_GetManagedWindow, 2564).
+-define(wxAuiManager_GetManager, 2565).
+-define(wxAuiManager_GetPane_1_1, 2566).
+-define(wxAuiManager_GetPane_1_0, 2567).
+-define(wxAuiManager_HideHint, 2568).
+-define(wxAuiManager_InsertPane, 2569).
+-define(wxAuiManager_LoadPaneInfo, 2570).
+-define(wxAuiManager_LoadPerspective, 2571).
+-define(wxAuiManager_SavePaneInfo, 2572).
+-define(wxAuiManager_SavePerspective, 2573).
+-define(wxAuiManager_SetArtProvider, 2574).
+-define(wxAuiManager_SetDockSizeConstraint, 2575).
+-define(wxAuiManager_SetFlags, 2576).
+-define(wxAuiManager_SetManagedWindow, 2577).
+-define(wxAuiManager_ShowHint, 2578).
+-define(wxAuiManager_UnInit, 2579).
+-define(wxAuiManager_Update, 2580).
+-define(wxAuiPaneInfo_new_0, 2581).
+-define(wxAuiPaneInfo_new_1, 2582).
+-define(wxAuiPaneInfo_destruct, 2583).
+-define(wxAuiPaneInfo_BestSize_1, 2584).
+-define(wxAuiPaneInfo_BestSize_2, 2585).
+-define(wxAuiPaneInfo_Bottom, 2586).
+-define(wxAuiPaneInfo_BottomDockable, 2587).
+-define(wxAuiPaneInfo_Caption, 2588).
+-define(wxAuiPaneInfo_CaptionVisible, 2589).
+-define(wxAuiPaneInfo_Centre, 2590).
+-define(wxAuiPaneInfo_CentrePane, 2591).
+-define(wxAuiPaneInfo_CloseButton, 2592).
+-define(wxAuiPaneInfo_DefaultPane, 2593).
+-define(wxAuiPaneInfo_DestroyOnClose, 2594).
+-define(wxAuiPaneInfo_Direction, 2595).
+-define(wxAuiPaneInfo_Dock, 2596).
+-define(wxAuiPaneInfo_Dockable, 2597).
+-define(wxAuiPaneInfo_Fixed, 2598).
+-define(wxAuiPaneInfo_Float, 2599).
+-define(wxAuiPaneInfo_Floatable, 2600).
+-define(wxAuiPaneInfo_FloatingPosition_1, 2601).
+-define(wxAuiPaneInfo_FloatingPosition_2, 2602).
+-define(wxAuiPaneInfo_FloatingSize_1, 2603).
+-define(wxAuiPaneInfo_FloatingSize_2, 2604).
+-define(wxAuiPaneInfo_Gripper, 2605).
+-define(wxAuiPaneInfo_GripperTop, 2606).
+-define(wxAuiPaneInfo_HasBorder, 2607).
+-define(wxAuiPaneInfo_HasCaption, 2608).
+-define(wxAuiPaneInfo_HasCloseButton, 2609).
+-define(wxAuiPaneInfo_HasFlag, 2610).
+-define(wxAuiPaneInfo_HasGripper, 2611).
+-define(wxAuiPaneInfo_HasGripperTop, 2612).
+-define(wxAuiPaneInfo_HasMaximizeButton, 2613).
+-define(wxAuiPaneInfo_HasMinimizeButton, 2614).
+-define(wxAuiPaneInfo_HasPinButton, 2615).
+-define(wxAuiPaneInfo_Hide, 2616).
+-define(wxAuiPaneInfo_IsBottomDockable, 2617).
+-define(wxAuiPaneInfo_IsDocked, 2618).
+-define(wxAuiPaneInfo_IsFixed, 2619).
+-define(wxAuiPaneInfo_IsFloatable, 2620).
+-define(wxAuiPaneInfo_IsFloating, 2621).
+-define(wxAuiPaneInfo_IsLeftDockable, 2622).
+-define(wxAuiPaneInfo_IsMovable, 2623).
+-define(wxAuiPaneInfo_IsOk, 2624).
+-define(wxAuiPaneInfo_IsResizable, 2625).
+-define(wxAuiPaneInfo_IsRightDockable, 2626).
+-define(wxAuiPaneInfo_IsShown, 2627).
+-define(wxAuiPaneInfo_IsToolbar, 2628).
+-define(wxAuiPaneInfo_IsTopDockable, 2629).
+-define(wxAuiPaneInfo_Layer, 2630).
+-define(wxAuiPaneInfo_Left, 2631).
+-define(wxAuiPaneInfo_LeftDockable, 2632).
+-define(wxAuiPaneInfo_MaxSize_1, 2633).
+-define(wxAuiPaneInfo_MaxSize_2, 2634).
+-define(wxAuiPaneInfo_MaximizeButton, 2635).
+-define(wxAuiPaneInfo_MinSize_1, 2636).
+-define(wxAuiPaneInfo_MinSize_2, 2637).
+-define(wxAuiPaneInfo_MinimizeButton, 2638).
+-define(wxAuiPaneInfo_Movable, 2639).
+-define(wxAuiPaneInfo_Name, 2640).
+-define(wxAuiPaneInfo_PaneBorder, 2641).
+-define(wxAuiPaneInfo_PinButton, 2642).
+-define(wxAuiPaneInfo_Position, 2643).
+-define(wxAuiPaneInfo_Resizable, 2644).
+-define(wxAuiPaneInfo_Right, 2645).
+-define(wxAuiPaneInfo_RightDockable, 2646).
+-define(wxAuiPaneInfo_Row, 2647).
+-define(wxAuiPaneInfo_SafeSet, 2648).
+-define(wxAuiPaneInfo_SetFlag, 2649).
+-define(wxAuiPaneInfo_Show, 2650).
+-define(wxAuiPaneInfo_ToolbarPane, 2651).
+-define(wxAuiPaneInfo_Top, 2652).
+-define(wxAuiPaneInfo_TopDockable, 2653).
+-define(wxAuiPaneInfo_Window, 2654).
+-define(wxAuiPaneInfo_GetWindow, 2655).
+-define(wxAuiPaneInfo_GetFrame, 2656).
+-define(wxAuiPaneInfo_GetDirection, 2657).
+-define(wxAuiPaneInfo_GetLayer, 2658).
+-define(wxAuiPaneInfo_GetRow, 2659).
+-define(wxAuiPaneInfo_GetPosition, 2660).
+-define(wxAuiPaneInfo_GetFloatingPosition, 2661).
+-define(wxAuiPaneInfo_GetFloatingSize, 2662).
+-define(wxAuiNotebook_new_0, 2663).
+-define(wxAuiNotebook_new_2, 2664).
+-define(wxAuiNotebook_AddPage, 2665).
+-define(wxAuiNotebook_Create, 2666).
+-define(wxAuiNotebook_DeletePage, 2667).
+-define(wxAuiNotebook_GetArtProvider, 2668).
+-define(wxAuiNotebook_GetPage, 2669).
+-define(wxAuiNotebook_GetPageBitmap, 2670).
+-define(wxAuiNotebook_GetPageCount, 2671).
+-define(wxAuiNotebook_GetPageIndex, 2672).
+-define(wxAuiNotebook_GetPageText, 2673).
+-define(wxAuiNotebook_GetSelection, 2674).
+-define(wxAuiNotebook_InsertPage, 2675).
+-define(wxAuiNotebook_RemovePage, 2676).
+-define(wxAuiNotebook_SetArtProvider, 2677).
+-define(wxAuiNotebook_SetFont, 2678).
+-define(wxAuiNotebook_SetPageBitmap, 2679).
+-define(wxAuiNotebook_SetPageText, 2680).
+-define(wxAuiNotebook_SetSelection, 2681).
+-define(wxAuiNotebook_SetTabCtrlHeight, 2682).
+-define(wxAuiNotebook_SetUniformBitmapSize, 2683).
+-define(wxAuiNotebook_destroy, 2684).
+-define(wxAuiTabArt_SetFlags, 2685).
+-define(wxAuiTabArt_SetMeasuringFont, 2686).
+-define(wxAuiTabArt_SetNormalFont, 2687).
+-define(wxAuiTabArt_SetSelectedFont, 2688).
+-define(wxAuiTabArt_SetColour, 2689).
+-define(wxAuiTabArt_SetActiveColour, 2690).
+-define(wxAuiDockArt_GetColour, 2691).
+-define(wxAuiDockArt_GetFont, 2692).
+-define(wxAuiDockArt_GetMetric, 2693).
+-define(wxAuiDockArt_SetColour, 2694).
+-define(wxAuiDockArt_SetFont, 2695).
+-define(wxAuiDockArt_SetMetric, 2696).
+-define(wxAuiSimpleTabArt_new, 2697).
+-define(wxAuiSimpleTabArt_destroy, 2698).
+-define(wxMDIParentFrame_new_0, 2699).
+-define(wxMDIParentFrame_new_4, 2700).
+-define(wxMDIParentFrame_destruct, 2701).
+-define(wxMDIParentFrame_ActivateNext, 2702).
+-define(wxMDIParentFrame_ActivatePrevious, 2703).
+-define(wxMDIParentFrame_ArrangeIcons, 2704).
+-define(wxMDIParentFrame_Cascade, 2705).
+-define(wxMDIParentFrame_Create, 2706).
+-define(wxMDIParentFrame_GetActiveChild, 2707).
+-define(wxMDIParentFrame_GetClientWindow, 2708).
+-define(wxMDIParentFrame_Tile, 2709).
+-define(wxMDIChildFrame_new_0, 2710).
+-define(wxMDIChildFrame_new_4, 2711).
+-define(wxMDIChildFrame_destruct, 2712).
+-define(wxMDIChildFrame_Activate, 2713).
+-define(wxMDIChildFrame_Create, 2714).
+-define(wxMDIChildFrame_Maximize, 2715).
+-define(wxMDIChildFrame_Restore, 2716).
+-define(wxMDIClientWindow_new_0, 2717).
+-define(wxMDIClientWindow_new_2, 2718).
+-define(wxMDIClientWindow_destruct, 2719).
+-define(wxMDIClientWindow_CreateClient, 2720).
+-define(wxLayoutAlgorithm_new, 2721).
+-define(wxLayoutAlgorithm_LayoutFrame, 2722).
+-define(wxLayoutAlgorithm_LayoutMDIFrame, 2723).
+-define(wxLayoutAlgorithm_LayoutWindow, 2724).
+-define(wxLayoutAlgorithm_destroy, 2725).
+-define(wxEvent_GetId, 2726).
+-define(wxEvent_GetSkipped, 2727).
+-define(wxEvent_GetTimestamp, 2728).
+-define(wxEvent_IsCommandEvent, 2729).
+-define(wxEvent_ResumePropagation, 2730).
+-define(wxEvent_ShouldPropagate, 2731).
+-define(wxEvent_Skip, 2732).
+-define(wxEvent_StopPropagation, 2733).
+-define(wxCommandEvent_getClientData, 2734).
+-define(wxCommandEvent_GetExtraLong, 2735).
+-define(wxCommandEvent_GetInt, 2736).
+-define(wxCommandEvent_GetSelection, 2737).
+-define(wxCommandEvent_GetString, 2738).
+-define(wxCommandEvent_IsChecked, 2739).
+-define(wxCommandEvent_IsSelection, 2740).
+-define(wxCommandEvent_SetInt, 2741).
+-define(wxCommandEvent_SetString, 2742).
+-define(wxScrollEvent_GetOrientation, 2743).
+-define(wxScrollEvent_GetPosition, 2744).
+-define(wxScrollWinEvent_GetOrientation, 2745).
+-define(wxScrollWinEvent_GetPosition, 2746).
+-define(wxMouseEvent_AltDown, 2747).
+-define(wxMouseEvent_Button, 2748).
+-define(wxMouseEvent_ButtonDClick, 2749).
+-define(wxMouseEvent_ButtonDown, 2750).
+-define(wxMouseEvent_ButtonUp, 2751).
+-define(wxMouseEvent_CmdDown, 2752).
+-define(wxMouseEvent_ControlDown, 2753).
+-define(wxMouseEvent_Dragging, 2754).
+-define(wxMouseEvent_Entering, 2755).
+-define(wxMouseEvent_GetButton, 2756).
+-define(wxMouseEvent_GetPosition, 2759).
+-define(wxMouseEvent_GetLogicalPosition, 2760).
+-define(wxMouseEvent_GetLinesPerAction, 2761).
+-define(wxMouseEvent_GetWheelRotation, 2762).
+-define(wxMouseEvent_GetWheelDelta, 2763).
+-define(wxMouseEvent_GetX, 2764).
+-define(wxMouseEvent_GetY, 2765).
+-define(wxMouseEvent_IsButton, 2766).
+-define(wxMouseEvent_IsPageScroll, 2767).
+-define(wxMouseEvent_Leaving, 2768).
+-define(wxMouseEvent_LeftDClick, 2769).
+-define(wxMouseEvent_LeftDown, 2770).
+-define(wxMouseEvent_LeftIsDown, 2771).
+-define(wxMouseEvent_LeftUp, 2772).
+-define(wxMouseEvent_MetaDown, 2773).
+-define(wxMouseEvent_MiddleDClick, 2774).
+-define(wxMouseEvent_MiddleDown, 2775).
+-define(wxMouseEvent_MiddleIsDown, 2776).
+-define(wxMouseEvent_MiddleUp, 2777).
+-define(wxMouseEvent_Moving, 2778).
+-define(wxMouseEvent_RightDClick, 2779).
+-define(wxMouseEvent_RightDown, 2780).
+-define(wxMouseEvent_RightIsDown, 2781).
+-define(wxMouseEvent_RightUp, 2782).
+-define(wxMouseEvent_ShiftDown, 2783).
+-define(wxSetCursorEvent_GetCursor, 2784).
+-define(wxSetCursorEvent_GetX, 2785).
+-define(wxSetCursorEvent_GetY, 2786).
+-define(wxSetCursorEvent_HasCursor, 2787).
+-define(wxSetCursorEvent_SetCursor, 2788).
+-define(wxKeyEvent_AltDown, 2789).
+-define(wxKeyEvent_CmdDown, 2790).
+-define(wxKeyEvent_ControlDown, 2791).
+-define(wxKeyEvent_GetKeyCode, 2792).
+-define(wxKeyEvent_GetModifiers, 2793).
+-define(wxKeyEvent_GetPosition, 2796).
+-define(wxKeyEvent_GetRawKeyCode, 2797).
+-define(wxKeyEvent_GetRawKeyFlags, 2798).
+-define(wxKeyEvent_GetUnicodeKey, 2799).
+-define(wxKeyEvent_GetX, 2800).
+-define(wxKeyEvent_GetY, 2801).
+-define(wxKeyEvent_HasModifiers, 2802).
+-define(wxKeyEvent_MetaDown, 2803).
+-define(wxKeyEvent_ShiftDown, 2804).
+-define(wxSizeEvent_GetSize, 2805).
+-define(wxMoveEvent_GetPosition, 2806).
+-define(wxEraseEvent_GetDC, 2807).
+-define(wxFocusEvent_GetWindow, 2808).
+-define(wxChildFocusEvent_GetWindow, 2809).
+-define(wxMenuEvent_GetMenu, 2810).
+-define(wxMenuEvent_GetMenuId, 2811).
+-define(wxMenuEvent_IsPopup, 2812).
+-define(wxCloseEvent_CanVeto, 2813).
+-define(wxCloseEvent_GetLoggingOff, 2814).
+-define(wxCloseEvent_SetCanVeto, 2815).
+-define(wxCloseEvent_SetLoggingOff, 2816).
+-define(wxCloseEvent_Veto, 2817).
+-define(wxShowEvent_SetShow, 2818).
+-define(wxShowEvent_GetShow, 2819).
+-define(wxIconizeEvent_Iconized, 2820).
+-define(wxJoystickEvent_ButtonDown, 2821).
+-define(wxJoystickEvent_ButtonIsDown, 2822).
+-define(wxJoystickEvent_ButtonUp, 2823).
+-define(wxJoystickEvent_GetButtonChange, 2824).
+-define(wxJoystickEvent_GetButtonState, 2825).
+-define(wxJoystickEvent_GetJoystick, 2826).
+-define(wxJoystickEvent_GetPosition, 2827).
+-define(wxJoystickEvent_GetZPosition, 2828).
+-define(wxJoystickEvent_IsButton, 2829).
+-define(wxJoystickEvent_IsMove, 2830).
+-define(wxJoystickEvent_IsZMove, 2831).
+-define(wxUpdateUIEvent_CanUpdate, 2832).
+-define(wxUpdateUIEvent_Check, 2833).
+-define(wxUpdateUIEvent_Enable, 2834).
+-define(wxUpdateUIEvent_Show, 2835).
+-define(wxUpdateUIEvent_GetChecked, 2836).
+-define(wxUpdateUIEvent_GetEnabled, 2837).
+-define(wxUpdateUIEvent_GetShown, 2838).
+-define(wxUpdateUIEvent_GetSetChecked, 2839).
+-define(wxUpdateUIEvent_GetSetEnabled, 2840).
+-define(wxUpdateUIEvent_GetSetShown, 2841).
+-define(wxUpdateUIEvent_GetSetText, 2842).
+-define(wxUpdateUIEvent_GetText, 2843).
+-define(wxUpdateUIEvent_GetMode, 2844).
+-define(wxUpdateUIEvent_GetUpdateInterval, 2845).
+-define(wxUpdateUIEvent_ResetUpdateTime, 2846).
+-define(wxUpdateUIEvent_SetMode, 2847).
+-define(wxUpdateUIEvent_SetText, 2848).
+-define(wxUpdateUIEvent_SetUpdateInterval, 2849).
+-define(wxMouseCaptureChangedEvent_GetCapturedWindow, 2850).
+-define(wxPaletteChangedEvent_SetChangedWindow, 2851).
+-define(wxPaletteChangedEvent_GetChangedWindow, 2852).
+-define(wxQueryNewPaletteEvent_SetPaletteRealized, 2853).
+-define(wxQueryNewPaletteEvent_GetPaletteRealized, 2854).
+-define(wxNavigationKeyEvent_GetDirection, 2855).
+-define(wxNavigationKeyEvent_SetDirection, 2856).
+-define(wxNavigationKeyEvent_IsWindowChange, 2857).
+-define(wxNavigationKeyEvent_SetWindowChange, 2858).
+-define(wxNavigationKeyEvent_IsFromTab, 2859).
+-define(wxNavigationKeyEvent_SetFromTab, 2860).
+-define(wxNavigationKeyEvent_GetCurrentFocus, 2861).
+-define(wxNavigationKeyEvent_SetCurrentFocus, 2862).
+-define(wxHelpEvent_GetOrigin, 2863).
+-define(wxHelpEvent_GetPosition, 2864).
+-define(wxHelpEvent_SetOrigin, 2865).
+-define(wxHelpEvent_SetPosition, 2866).
+-define(wxContextMenuEvent_GetPosition, 2867).
+-define(wxContextMenuEvent_SetPosition, 2868).
+-define(wxIdleEvent_CanSend, 2869).
+-define(wxIdleEvent_GetMode, 2870).
+-define(wxIdleEvent_RequestMore, 2871).
+-define(wxIdleEvent_MoreRequested, 2872).
+-define(wxIdleEvent_SetMode, 2873).
+-define(wxGridEvent_AltDown, 2874).
+-define(wxGridEvent_ControlDown, 2875).
+-define(wxGridEvent_GetCol, 2876).
+-define(wxGridEvent_GetPosition, 2877).
+-define(wxGridEvent_GetRow, 2878).
+-define(wxGridEvent_MetaDown, 2879).
+-define(wxGridEvent_Selecting, 2880).
+-define(wxGridEvent_ShiftDown, 2881).
+-define(wxNotifyEvent_Allow, 2882).
+-define(wxNotifyEvent_IsAllowed, 2883).
+-define(wxNotifyEvent_Veto, 2884).
+-define(wxSashEvent_GetEdge, 2885).
+-define(wxSashEvent_GetDragRect, 2886).
+-define(wxSashEvent_GetDragStatus, 2887).
+-define(wxListEvent_GetCacheFrom, 2888).
+-define(wxListEvent_GetCacheTo, 2889).
+-define(wxListEvent_GetKeyCode, 2890).
+-define(wxListEvent_GetIndex, 2891).
+-define(wxListEvent_GetColumn, 2892).
+-define(wxListEvent_GetPoint, 2893).
+-define(wxListEvent_GetLabel, 2894).
+-define(wxListEvent_GetText, 2895).
+-define(wxListEvent_GetImage, 2896).
+-define(wxListEvent_GetData, 2897).
+-define(wxListEvent_GetMask, 2898).
+-define(wxListEvent_GetItem, 2899).
+-define(wxListEvent_IsEditCancelled, 2900).
+-define(wxDateEvent_GetDate, 2901).
+-define(wxCalendarEvent_GetWeekDay, 2902).
+-define(wxFileDirPickerEvent_GetPath, 2903).
+-define(wxColourPickerEvent_GetColour, 2904).
+-define(wxFontPickerEvent_GetFont, 2905).
+-define(wxStyledTextEvent_GetPosition, 2906).
+-define(wxStyledTextEvent_GetKey, 2907).
+-define(wxStyledTextEvent_GetModifiers, 2908).
+-define(wxStyledTextEvent_GetModificationType, 2909).
+-define(wxStyledTextEvent_GetText, 2910).
+-define(wxStyledTextEvent_GetLength, 2911).
+-define(wxStyledTextEvent_GetLinesAdded, 2912).
+-define(wxStyledTextEvent_GetLine, 2913).
+-define(wxStyledTextEvent_GetFoldLevelNow, 2914).
+-define(wxStyledTextEvent_GetFoldLevelPrev, 2915).
+-define(wxStyledTextEvent_GetMargin, 2916).
+-define(wxStyledTextEvent_GetMessage, 2917).
+-define(wxStyledTextEvent_GetWParam, 2918).
+-define(wxStyledTextEvent_GetLParam, 2919).
+-define(wxStyledTextEvent_GetListType, 2920).
+-define(wxStyledTextEvent_GetX, 2921).
+-define(wxStyledTextEvent_GetY, 2922).
+-define(wxStyledTextEvent_GetDragText, 2923).
+-define(wxStyledTextEvent_GetDragAllowMove, 2924).
+-define(wxStyledTextEvent_GetDragResult, 2925).
+-define(wxStyledTextEvent_GetShift, 2926).
+-define(wxStyledTextEvent_GetControl, 2927).
+-define(wxStyledTextEvent_GetAlt, 2928).
+-define(utils_wxGetKeyState, 2929).
+-define(utils_wxGetMousePosition, 2930).
+-define(utils_wxGetMouseState, 2931).
+-define(utils_wxSetDetectableAutoRepeat, 2932).
+-define(utils_wxBell, 2933).
+-define(utils_wxFindMenuItemId, 2934).
+-define(utils_wxGenericFindWindowAtPoint, 2935).
+-define(utils_wxFindWindowAtPoint, 2936).
+-define(utils_wxBeginBusyCursor, 2937).
+-define(utils_wxEndBusyCursor, 2938).
+-define(utils_wxIsBusy, 2939).
+-define(utils_wxShutdown, 2940).
+-define(utils_wxShell, 2941).
+-define(utils_wxLaunchDefaultBrowser, 2942).
+-define(utils_wxGetEmailAddress, 2943).
+-define(utils_wxGetUserId, 2944).
+-define(utils_wxGetHomeDir, 2945).
+-define(utils_wxNewId, 2946).
+-define(utils_wxRegisterId, 2947).
+-define(utils_wxGetCurrentId, 2948).
+-define(utils_wxGetOsDescription, 2949).
+-define(utils_wxIsPlatformLittleEndian, 2950).
+-define(utils_wxIsPlatform64Bit, 2951).
+-define(gdicmn_wxDisplaySize, 2952).
+-define(gdicmn_wxSetCursor, 2953).
+-define(wxPrintout_new, 2954).
+-define(wxPrintout_destruct, 2955).
+-define(wxPrintout_GetDC, 2956).
+-define(wxPrintout_GetPageSizeMM, 2957).
+-define(wxPrintout_GetPageSizePixels, 2958).
+-define(wxPrintout_GetPaperRectPixels, 2959).
+-define(wxPrintout_GetPPIPrinter, 2960).
+-define(wxPrintout_GetPPIScreen, 2961).
+-define(wxPrintout_GetTitle, 2962).
+-define(wxPrintout_IsPreview, 2963).
+-define(wxPrintout_FitThisSizeToPaper, 2964).
+-define(wxPrintout_FitThisSizeToPage, 2965).
+-define(wxPrintout_FitThisSizeToPageMargins, 2966).
+-define(wxPrintout_MapScreenSizeToPaper, 2967).
+-define(wxPrintout_MapScreenSizeToPage, 2968).
+-define(wxPrintout_MapScreenSizeToPageMargins, 2969).
+-define(wxPrintout_MapScreenSizeToDevice, 2970).
+-define(wxPrintout_GetLogicalPaperRect, 2971).
+-define(wxPrintout_GetLogicalPageRect, 2972).
+-define(wxPrintout_GetLogicalPageMarginsRect, 2973).
+-define(wxPrintout_SetLogicalOrigin, 2974).
+-define(wxPrintout_OffsetLogicalOrigin, 2975).
+-define(wxStyledTextCtrl_new_2, 2976).
+-define(wxStyledTextCtrl_new_0, 2977).
+-define(wxStyledTextCtrl_destruct, 2978).
+-define(wxStyledTextCtrl_Create, 2979).
+-define(wxStyledTextCtrl_AddText, 2980).
+-define(wxStyledTextCtrl_AddStyledText, 2981).
+-define(wxStyledTextCtrl_InsertText, 2982).
+-define(wxStyledTextCtrl_ClearAll, 2983).
+-define(wxStyledTextCtrl_ClearDocumentStyle, 2984).
+-define(wxStyledTextCtrl_GetLength, 2985).
+-define(wxStyledTextCtrl_GetCharAt, 2986).
+-define(wxStyledTextCtrl_GetCurrentPos, 2987).
+-define(wxStyledTextCtrl_GetAnchor, 2988).
+-define(wxStyledTextCtrl_GetStyleAt, 2989).
+-define(wxStyledTextCtrl_Redo, 2990).
+-define(wxStyledTextCtrl_SetUndoCollection, 2991).
+-define(wxStyledTextCtrl_SelectAll, 2992).
+-define(wxStyledTextCtrl_SetSavePoint, 2993).
+-define(wxStyledTextCtrl_GetStyledText, 2994).
+-define(wxStyledTextCtrl_CanRedo, 2995).
+-define(wxStyledTextCtrl_MarkerLineFromHandle, 2996).
+-define(wxStyledTextCtrl_MarkerDeleteHandle, 2997).
+-define(wxStyledTextCtrl_GetUndoCollection, 2998).
+-define(wxStyledTextCtrl_GetViewWhiteSpace, 2999).
+-define(wxStyledTextCtrl_SetViewWhiteSpace, 3000).
+-define(wxStyledTextCtrl_PositionFromPoint, 3001).
+-define(wxStyledTextCtrl_PositionFromPointClose, 3002).
+-define(wxStyledTextCtrl_GotoLine, 3003).
+-define(wxStyledTextCtrl_GotoPos, 3004).
+-define(wxStyledTextCtrl_SetAnchor, 3005).
+-define(wxStyledTextCtrl_GetCurLine, 3006).
+-define(wxStyledTextCtrl_GetEndStyled, 3007).
+-define(wxStyledTextCtrl_ConvertEOLs, 3008).
+-define(wxStyledTextCtrl_GetEOLMode, 3009).
+-define(wxStyledTextCtrl_SetEOLMode, 3010).
+-define(wxStyledTextCtrl_StartStyling, 3011).
+-define(wxStyledTextCtrl_SetStyling, 3012).
+-define(wxStyledTextCtrl_GetBufferedDraw, 3013).
+-define(wxStyledTextCtrl_SetBufferedDraw, 3014).
+-define(wxStyledTextCtrl_SetTabWidth, 3015).
+-define(wxStyledTextCtrl_GetTabWidth, 3016).
+-define(wxStyledTextCtrl_SetCodePage, 3017).
+-define(wxStyledTextCtrl_MarkerDefine, 3018).
+-define(wxStyledTextCtrl_MarkerSetForeground, 3019).
+-define(wxStyledTextCtrl_MarkerSetBackground, 3020).
+-define(wxStyledTextCtrl_MarkerAdd, 3021).
+-define(wxStyledTextCtrl_MarkerDelete, 3022).
+-define(wxStyledTextCtrl_MarkerDeleteAll, 3023).
+-define(wxStyledTextCtrl_MarkerGet, 3024).
+-define(wxStyledTextCtrl_MarkerNext, 3025).
+-define(wxStyledTextCtrl_MarkerPrevious, 3026).
+-define(wxStyledTextCtrl_MarkerDefineBitmap, 3027).
+-define(wxStyledTextCtrl_MarkerAddSet, 3028).
+-define(wxStyledTextCtrl_MarkerSetAlpha, 3029).
+-define(wxStyledTextCtrl_SetMarginType, 3030).
+-define(wxStyledTextCtrl_GetMarginType, 3031).
+-define(wxStyledTextCtrl_SetMarginWidth, 3032).
+-define(wxStyledTextCtrl_GetMarginWidth, 3033).
+-define(wxStyledTextCtrl_SetMarginMask, 3034).
+-define(wxStyledTextCtrl_GetMarginMask, 3035).
+-define(wxStyledTextCtrl_SetMarginSensitive, 3036).
+-define(wxStyledTextCtrl_GetMarginSensitive, 3037).
+-define(wxStyledTextCtrl_StyleClearAll, 3038).
+-define(wxStyledTextCtrl_StyleSetForeground, 3039).
+-define(wxStyledTextCtrl_StyleSetBackground, 3040).
+-define(wxStyledTextCtrl_StyleSetBold, 3041).
+-define(wxStyledTextCtrl_StyleSetItalic, 3042).
+-define(wxStyledTextCtrl_StyleSetSize, 3043).
+-define(wxStyledTextCtrl_StyleSetFaceName, 3044).
+-define(wxStyledTextCtrl_StyleSetEOLFilled, 3045).
+-define(wxStyledTextCtrl_StyleResetDefault, 3046).
+-define(wxStyledTextCtrl_StyleSetUnderline, 3047).
+-define(wxStyledTextCtrl_StyleSetCase, 3048).
+-define(wxStyledTextCtrl_StyleSetHotSpot, 3049).
+-define(wxStyledTextCtrl_SetSelForeground, 3050).
+-define(wxStyledTextCtrl_SetSelBackground, 3051).
+-define(wxStyledTextCtrl_GetSelAlpha, 3052).
+-define(wxStyledTextCtrl_SetSelAlpha, 3053).
+-define(wxStyledTextCtrl_SetCaretForeground, 3054).
+-define(wxStyledTextCtrl_CmdKeyAssign, 3055).
+-define(wxStyledTextCtrl_CmdKeyClear, 3056).
+-define(wxStyledTextCtrl_CmdKeyClearAll, 3057).
+-define(wxStyledTextCtrl_SetStyleBytes, 3058).
+-define(wxStyledTextCtrl_StyleSetVisible, 3059).
+-define(wxStyledTextCtrl_GetCaretPeriod, 3060).
+-define(wxStyledTextCtrl_SetCaretPeriod, 3061).
+-define(wxStyledTextCtrl_SetWordChars, 3062).
+-define(wxStyledTextCtrl_BeginUndoAction, 3063).
+-define(wxStyledTextCtrl_EndUndoAction, 3064).
+-define(wxStyledTextCtrl_IndicatorSetStyle, 3065).
+-define(wxStyledTextCtrl_IndicatorGetStyle, 3066).
+-define(wxStyledTextCtrl_IndicatorSetForeground, 3067).
+-define(wxStyledTextCtrl_IndicatorGetForeground, 3068).
+-define(wxStyledTextCtrl_SetWhitespaceForeground, 3069).
+-define(wxStyledTextCtrl_SetWhitespaceBackground, 3070).
+-define(wxStyledTextCtrl_GetStyleBits, 3071).
+-define(wxStyledTextCtrl_SetLineState, 3072).
+-define(wxStyledTextCtrl_GetLineState, 3073).
+-define(wxStyledTextCtrl_GetMaxLineState, 3074).
+-define(wxStyledTextCtrl_GetCaretLineVisible, 3075).
+-define(wxStyledTextCtrl_SetCaretLineVisible, 3076).
+-define(wxStyledTextCtrl_GetCaretLineBackground, 3077).
+-define(wxStyledTextCtrl_SetCaretLineBackground, 3078).
+-define(wxStyledTextCtrl_AutoCompShow, 3079).
+-define(wxStyledTextCtrl_AutoCompCancel, 3080).
+-define(wxStyledTextCtrl_AutoCompActive, 3081).
+-define(wxStyledTextCtrl_AutoCompPosStart, 3082).
+-define(wxStyledTextCtrl_AutoCompComplete, 3083).
+-define(wxStyledTextCtrl_AutoCompStops, 3084).
+-define(wxStyledTextCtrl_AutoCompSetSeparator, 3085).
+-define(wxStyledTextCtrl_AutoCompGetSeparator, 3086).
+-define(wxStyledTextCtrl_AutoCompSelect, 3087).
+-define(wxStyledTextCtrl_AutoCompSetCancelAtStart, 3088).
+-define(wxStyledTextCtrl_AutoCompGetCancelAtStart, 3089).
+-define(wxStyledTextCtrl_AutoCompSetFillUps, 3090).
+-define(wxStyledTextCtrl_AutoCompSetChooseSingle, 3091).
+-define(wxStyledTextCtrl_AutoCompGetChooseSingle, 3092).
+-define(wxStyledTextCtrl_AutoCompSetIgnoreCase, 3093).
+-define(wxStyledTextCtrl_AutoCompGetIgnoreCase, 3094).
+-define(wxStyledTextCtrl_UserListShow, 3095).
+-define(wxStyledTextCtrl_AutoCompSetAutoHide, 3096).
+-define(wxStyledTextCtrl_AutoCompGetAutoHide, 3097).
+-define(wxStyledTextCtrl_AutoCompSetDropRestOfWord, 3098).
+-define(wxStyledTextCtrl_AutoCompGetDropRestOfWord, 3099).
+-define(wxStyledTextCtrl_RegisterImage, 3100).
+-define(wxStyledTextCtrl_ClearRegisteredImages, 3101).
+-define(wxStyledTextCtrl_AutoCompGetTypeSeparator, 3102).
+-define(wxStyledTextCtrl_AutoCompSetTypeSeparator, 3103).
+-define(wxStyledTextCtrl_AutoCompSetMaxWidth, 3104).
+-define(wxStyledTextCtrl_AutoCompGetMaxWidth, 3105).
+-define(wxStyledTextCtrl_AutoCompSetMaxHeight, 3106).
+-define(wxStyledTextCtrl_AutoCompGetMaxHeight, 3107).
+-define(wxStyledTextCtrl_SetIndent, 3108).
+-define(wxStyledTextCtrl_GetIndent, 3109).
+-define(wxStyledTextCtrl_SetUseTabs, 3110).
+-define(wxStyledTextCtrl_GetUseTabs, 3111).
+-define(wxStyledTextCtrl_SetLineIndentation, 3112).
+-define(wxStyledTextCtrl_GetLineIndentation, 3113).
+-define(wxStyledTextCtrl_GetLineIndentPosition, 3114).
+-define(wxStyledTextCtrl_GetColumn, 3115).
+-define(wxStyledTextCtrl_SetUseHorizontalScrollBar, 3116).
+-define(wxStyledTextCtrl_GetUseHorizontalScrollBar, 3117).
+-define(wxStyledTextCtrl_SetIndentationGuides, 3118).
+-define(wxStyledTextCtrl_GetIndentationGuides, 3119).
+-define(wxStyledTextCtrl_SetHighlightGuide, 3120).
+-define(wxStyledTextCtrl_GetHighlightGuide, 3121).
+-define(wxStyledTextCtrl_GetLineEndPosition, 3122).
+-define(wxStyledTextCtrl_GetCodePage, 3123).
+-define(wxStyledTextCtrl_GetCaretForeground, 3124).
+-define(wxStyledTextCtrl_GetReadOnly, 3125).
+-define(wxStyledTextCtrl_SetCurrentPos, 3126).
+-define(wxStyledTextCtrl_SetSelectionStart, 3127).
+-define(wxStyledTextCtrl_GetSelectionStart, 3128).
+-define(wxStyledTextCtrl_SetSelectionEnd, 3129).
+-define(wxStyledTextCtrl_GetSelectionEnd, 3130).
+-define(wxStyledTextCtrl_SetPrintMagnification, 3131).
+-define(wxStyledTextCtrl_GetPrintMagnification, 3132).
+-define(wxStyledTextCtrl_SetPrintColourMode, 3133).
+-define(wxStyledTextCtrl_GetPrintColourMode, 3134).
+-define(wxStyledTextCtrl_FindText, 3135).
+-define(wxStyledTextCtrl_FormatRange, 3136).
+-define(wxStyledTextCtrl_GetFirstVisibleLine, 3137).
+-define(wxStyledTextCtrl_GetLine, 3138).
+-define(wxStyledTextCtrl_GetLineCount, 3139).
+-define(wxStyledTextCtrl_SetMarginLeft, 3140).
+-define(wxStyledTextCtrl_GetMarginLeft, 3141).
+-define(wxStyledTextCtrl_SetMarginRight, 3142).
+-define(wxStyledTextCtrl_GetMarginRight, 3143).
+-define(wxStyledTextCtrl_GetModify, 3144).
+-define(wxStyledTextCtrl_SetSelection, 3145).
+-define(wxStyledTextCtrl_GetSelectedText, 3146).
+-define(wxStyledTextCtrl_GetTextRange, 3147).
+-define(wxStyledTextCtrl_HideSelection, 3148).
+-define(wxStyledTextCtrl_LineFromPosition, 3149).
+-define(wxStyledTextCtrl_PositionFromLine, 3150).
+-define(wxStyledTextCtrl_LineScroll, 3151).
+-define(wxStyledTextCtrl_EnsureCaretVisible, 3152).
+-define(wxStyledTextCtrl_ReplaceSelection, 3153).
+-define(wxStyledTextCtrl_SetReadOnly, 3154).
+-define(wxStyledTextCtrl_CanPaste, 3155).
+-define(wxStyledTextCtrl_CanUndo, 3156).
+-define(wxStyledTextCtrl_EmptyUndoBuffer, 3157).
+-define(wxStyledTextCtrl_Undo, 3158).
+-define(wxStyledTextCtrl_Cut, 3159).
+-define(wxStyledTextCtrl_Copy, 3160).
+-define(wxStyledTextCtrl_Paste, 3161).
+-define(wxStyledTextCtrl_Clear, 3162).
+-define(wxStyledTextCtrl_SetText, 3163).
+-define(wxStyledTextCtrl_GetText, 3164).
+-define(wxStyledTextCtrl_GetTextLength, 3165).
+-define(wxStyledTextCtrl_GetOvertype, 3166).
+-define(wxStyledTextCtrl_SetCaretWidth, 3167).
+-define(wxStyledTextCtrl_GetCaretWidth, 3168).
+-define(wxStyledTextCtrl_SetTargetStart, 3169).
+-define(wxStyledTextCtrl_GetTargetStart, 3170).
+-define(wxStyledTextCtrl_SetTargetEnd, 3171).
+-define(wxStyledTextCtrl_GetTargetEnd, 3172).
+-define(wxStyledTextCtrl_ReplaceTarget, 3173).
+-define(wxStyledTextCtrl_SearchInTarget, 3174).
+-define(wxStyledTextCtrl_SetSearchFlags, 3175).
+-define(wxStyledTextCtrl_GetSearchFlags, 3176).
+-define(wxStyledTextCtrl_CallTipShow, 3177).
+-define(wxStyledTextCtrl_CallTipCancel, 3178).
+-define(wxStyledTextCtrl_CallTipActive, 3179).
+-define(wxStyledTextCtrl_CallTipPosAtStart, 3180).
+-define(wxStyledTextCtrl_CallTipSetHighlight, 3181).
+-define(wxStyledTextCtrl_CallTipSetBackground, 3182).
+-define(wxStyledTextCtrl_CallTipSetForeground, 3183).
+-define(wxStyledTextCtrl_CallTipSetForegroundHighlight, 3184).
+-define(wxStyledTextCtrl_CallTipUseStyle, 3185).
+-define(wxStyledTextCtrl_VisibleFromDocLine, 3186).
+-define(wxStyledTextCtrl_DocLineFromVisible, 3187).
+-define(wxStyledTextCtrl_WrapCount, 3188).
+-define(wxStyledTextCtrl_SetFoldLevel, 3189).
+-define(wxStyledTextCtrl_GetFoldLevel, 3190).
+-define(wxStyledTextCtrl_GetLastChild, 3191).
+-define(wxStyledTextCtrl_GetFoldParent, 3192).
+-define(wxStyledTextCtrl_ShowLines, 3193).
+-define(wxStyledTextCtrl_HideLines, 3194).
+-define(wxStyledTextCtrl_GetLineVisible, 3195).
+-define(wxStyledTextCtrl_SetFoldExpanded, 3196).
+-define(wxStyledTextCtrl_GetFoldExpanded, 3197).
+-define(wxStyledTextCtrl_ToggleFold, 3198).
+-define(wxStyledTextCtrl_EnsureVisible, 3199).
+-define(wxStyledTextCtrl_SetFoldFlags, 3200).
+-define(wxStyledTextCtrl_EnsureVisibleEnforcePolicy, 3201).
+-define(wxStyledTextCtrl_SetTabIndents, 3202).
+-define(wxStyledTextCtrl_GetTabIndents, 3203).
+-define(wxStyledTextCtrl_SetBackSpaceUnIndents, 3204).
+-define(wxStyledTextCtrl_GetBackSpaceUnIndents, 3205).
+-define(wxStyledTextCtrl_SetMouseDwellTime, 3206).
+-define(wxStyledTextCtrl_GetMouseDwellTime, 3207).
+-define(wxStyledTextCtrl_WordStartPosition, 3208).
+-define(wxStyledTextCtrl_WordEndPosition, 3209).
+-define(wxStyledTextCtrl_SetWrapMode, 3210).
+-define(wxStyledTextCtrl_GetWrapMode, 3211).
+-define(wxStyledTextCtrl_SetWrapVisualFlags, 3212).
+-define(wxStyledTextCtrl_GetWrapVisualFlags, 3213).
+-define(wxStyledTextCtrl_SetWrapVisualFlagsLocation, 3214).
+-define(wxStyledTextCtrl_GetWrapVisualFlagsLocation, 3215).
+-define(wxStyledTextCtrl_SetWrapStartIndent, 3216).
+-define(wxStyledTextCtrl_GetWrapStartIndent, 3217).
+-define(wxStyledTextCtrl_SetLayoutCache, 3218).
+-define(wxStyledTextCtrl_GetLayoutCache, 3219).
+-define(wxStyledTextCtrl_SetScrollWidth, 3220).
+-define(wxStyledTextCtrl_GetScrollWidth, 3221).
+-define(wxStyledTextCtrl_TextWidth, 3222).
+-define(wxStyledTextCtrl_GetEndAtLastLine, 3223).
+-define(wxStyledTextCtrl_TextHeight, 3224).
+-define(wxStyledTextCtrl_SetUseVerticalScrollBar, 3225).
+-define(wxStyledTextCtrl_GetUseVerticalScrollBar, 3226).
+-define(wxStyledTextCtrl_AppendText, 3227).
+-define(wxStyledTextCtrl_GetTwoPhaseDraw, 3228).
+-define(wxStyledTextCtrl_SetTwoPhaseDraw, 3229).
+-define(wxStyledTextCtrl_TargetFromSelection, 3230).
+-define(wxStyledTextCtrl_LinesJoin, 3231).
+-define(wxStyledTextCtrl_LinesSplit, 3232).
+-define(wxStyledTextCtrl_SetFoldMarginColour, 3233).
+-define(wxStyledTextCtrl_SetFoldMarginHiColour, 3234).
+-define(wxStyledTextCtrl_LineDown, 3235).
+-define(wxStyledTextCtrl_LineDownExtend, 3236).
+-define(wxStyledTextCtrl_LineUp, 3237).
+-define(wxStyledTextCtrl_LineUpExtend, 3238).
+-define(wxStyledTextCtrl_CharLeft, 3239).
+-define(wxStyledTextCtrl_CharLeftExtend, 3240).
+-define(wxStyledTextCtrl_CharRight, 3241).
+-define(wxStyledTextCtrl_CharRightExtend, 3242).
+-define(wxStyledTextCtrl_WordLeft, 3243).
+-define(wxStyledTextCtrl_WordLeftExtend, 3244).
+-define(wxStyledTextCtrl_WordRight, 3245).
+-define(wxStyledTextCtrl_WordRightExtend, 3246).
+-define(wxStyledTextCtrl_Home, 3247).
+-define(wxStyledTextCtrl_HomeExtend, 3248).
+-define(wxStyledTextCtrl_LineEnd, 3249).
+-define(wxStyledTextCtrl_LineEndExtend, 3250).
+-define(wxStyledTextCtrl_DocumentStart, 3251).
+-define(wxStyledTextCtrl_DocumentStartExtend, 3252).
+-define(wxStyledTextCtrl_DocumentEnd, 3253).
+-define(wxStyledTextCtrl_DocumentEndExtend, 3254).
+-define(wxStyledTextCtrl_PageUp, 3255).
+-define(wxStyledTextCtrl_PageUpExtend, 3256).
+-define(wxStyledTextCtrl_PageDown, 3257).
+-define(wxStyledTextCtrl_PageDownExtend, 3258).
+-define(wxStyledTextCtrl_EditToggleOvertype, 3259).
+-define(wxStyledTextCtrl_Cancel, 3260).
+-define(wxStyledTextCtrl_DeleteBack, 3261).
+-define(wxStyledTextCtrl_Tab, 3262).
+-define(wxStyledTextCtrl_BackTab, 3263).
+-define(wxStyledTextCtrl_NewLine, 3264).
+-define(wxStyledTextCtrl_FormFeed, 3265).
+-define(wxStyledTextCtrl_VCHome, 3266).
+-define(wxStyledTextCtrl_VCHomeExtend, 3267).
+-define(wxStyledTextCtrl_ZoomIn, 3268).
+-define(wxStyledTextCtrl_ZoomOut, 3269).
+-define(wxStyledTextCtrl_DelWordLeft, 3270).
+-define(wxStyledTextCtrl_DelWordRight, 3271).
+-define(wxStyledTextCtrl_LineCut, 3272).
+-define(wxStyledTextCtrl_LineDelete, 3273).
+-define(wxStyledTextCtrl_LineTranspose, 3274).
+-define(wxStyledTextCtrl_LineDuplicate, 3275).
+-define(wxStyledTextCtrl_LowerCase, 3276).
+-define(wxStyledTextCtrl_UpperCase, 3277).
+-define(wxStyledTextCtrl_LineScrollDown, 3278).
+-define(wxStyledTextCtrl_LineScrollUp, 3279).
+-define(wxStyledTextCtrl_DeleteBackNotLine, 3280).
+-define(wxStyledTextCtrl_HomeDisplay, 3281).
+-define(wxStyledTextCtrl_HomeDisplayExtend, 3282).
+-define(wxStyledTextCtrl_LineEndDisplay, 3283).
+-define(wxStyledTextCtrl_LineEndDisplayExtend, 3284).
+-define(wxStyledTextCtrl_HomeWrapExtend, 3285).
+-define(wxStyledTextCtrl_LineEndWrap, 3286).
+-define(wxStyledTextCtrl_LineEndWrapExtend, 3287).
+-define(wxStyledTextCtrl_VCHomeWrap, 3288).
+-define(wxStyledTextCtrl_VCHomeWrapExtend, 3289).
+-define(wxStyledTextCtrl_LineCopy, 3290).
+-define(wxStyledTextCtrl_MoveCaretInsideView, 3291).
+-define(wxStyledTextCtrl_LineLength, 3292).
+-define(wxStyledTextCtrl_BraceHighlight, 3293).
+-define(wxStyledTextCtrl_BraceBadLight, 3294).
+-define(wxStyledTextCtrl_BraceMatch, 3295).
+-define(wxStyledTextCtrl_GetViewEOL, 3296).
+-define(wxStyledTextCtrl_SetViewEOL, 3297).
+-define(wxStyledTextCtrl_SetModEventMask, 3298).
+-define(wxStyledTextCtrl_GetEdgeColumn, 3299).
+-define(wxStyledTextCtrl_SetEdgeColumn, 3300).
+-define(wxStyledTextCtrl_SetEdgeMode, 3301).
+-define(wxStyledTextCtrl_GetEdgeMode, 3302).
+-define(wxStyledTextCtrl_GetEdgeColour, 3303).
+-define(wxStyledTextCtrl_SetEdgeColour, 3304).
+-define(wxStyledTextCtrl_SearchAnchor, 3305).
+-define(wxStyledTextCtrl_SearchNext, 3306).
+-define(wxStyledTextCtrl_SearchPrev, 3307).
+-define(wxStyledTextCtrl_LinesOnScreen, 3308).
+-define(wxStyledTextCtrl_UsePopUp, 3309).
+-define(wxStyledTextCtrl_SelectionIsRectangle, 3310).
+-define(wxStyledTextCtrl_SetZoom, 3311).
+-define(wxStyledTextCtrl_GetZoom, 3312).
+-define(wxStyledTextCtrl_GetModEventMask, 3313).
+-define(wxStyledTextCtrl_SetSTCFocus, 3314).
+-define(wxStyledTextCtrl_GetSTCFocus, 3315).
+-define(wxStyledTextCtrl_SetStatus, 3316).
+-define(wxStyledTextCtrl_GetStatus, 3317).
+-define(wxStyledTextCtrl_SetMouseDownCaptures, 3318).
+-define(wxStyledTextCtrl_GetMouseDownCaptures, 3319).
+-define(wxStyledTextCtrl_SetSTCCursor, 3320).
+-define(wxStyledTextCtrl_GetSTCCursor, 3321).
+-define(wxStyledTextCtrl_SetControlCharSymbol, 3322).
+-define(wxStyledTextCtrl_GetControlCharSymbol, 3323).
+-define(wxStyledTextCtrl_WordPartLeft, 3324).
+-define(wxStyledTextCtrl_WordPartLeftExtend, 3325).
+-define(wxStyledTextCtrl_WordPartRight, 3326).
+-define(wxStyledTextCtrl_WordPartRightExtend, 3327).
+-define(wxStyledTextCtrl_SetVisiblePolicy, 3328).
+-define(wxStyledTextCtrl_DelLineLeft, 3329).
+-define(wxStyledTextCtrl_DelLineRight, 3330).
+-define(wxStyledTextCtrl_GetXOffset, 3331).
+-define(wxStyledTextCtrl_ChooseCaretX, 3332).
+-define(wxStyledTextCtrl_SetXCaretPolicy, 3333).
+-define(wxStyledTextCtrl_SetYCaretPolicy, 3334).
+-define(wxStyledTextCtrl_GetPrintWrapMode, 3335).
+-define(wxStyledTextCtrl_SetHotspotActiveForeground, 3336).
+-define(wxStyledTextCtrl_SetHotspotActiveBackground, 3337).
+-define(wxStyledTextCtrl_SetHotspotActiveUnderline, 3338).
+-define(wxStyledTextCtrl_SetHotspotSingleLine, 3339).
+-define(wxStyledTextCtrl_ParaDownExtend, 3340).
+-define(wxStyledTextCtrl_ParaUp, 3341).
+-define(wxStyledTextCtrl_ParaUpExtend, 3342).
+-define(wxStyledTextCtrl_PositionBefore, 3343).
+-define(wxStyledTextCtrl_PositionAfter, 3344).
+-define(wxStyledTextCtrl_CopyRange, 3345).
+-define(wxStyledTextCtrl_CopyText, 3346).
+-define(wxStyledTextCtrl_SetSelectionMode, 3347).
+-define(wxStyledTextCtrl_GetSelectionMode, 3348).
+-define(wxStyledTextCtrl_LineDownRectExtend, 3349).
+-define(wxStyledTextCtrl_LineUpRectExtend, 3350).
+-define(wxStyledTextCtrl_CharLeftRectExtend, 3351).
+-define(wxStyledTextCtrl_CharRightRectExtend, 3352).
+-define(wxStyledTextCtrl_HomeRectExtend, 3353).
+-define(wxStyledTextCtrl_VCHomeRectExtend, 3354).
+-define(wxStyledTextCtrl_LineEndRectExtend, 3355).
+-define(wxStyledTextCtrl_PageUpRectExtend, 3356).
+-define(wxStyledTextCtrl_PageDownRectExtend, 3357).
+-define(wxStyledTextCtrl_StutteredPageUp, 3358).
+-define(wxStyledTextCtrl_StutteredPageUpExtend, 3359).
+-define(wxStyledTextCtrl_StutteredPageDown, 3360).
+-define(wxStyledTextCtrl_StutteredPageDownExtend, 3361).
+-define(wxStyledTextCtrl_WordLeftEnd, 3362).
+-define(wxStyledTextCtrl_WordLeftEndExtend, 3363).
+-define(wxStyledTextCtrl_WordRightEnd, 3364).
+-define(wxStyledTextCtrl_WordRightEndExtend, 3365).
+-define(wxStyledTextCtrl_SetWhitespaceChars, 3366).
+-define(wxStyledTextCtrl_SetCharsDefault, 3367).
+-define(wxStyledTextCtrl_AutoCompGetCurrent, 3368).
+-define(wxStyledTextCtrl_Allocate, 3369).
+-define(wxStyledTextCtrl_FindColumn, 3370).
+-define(wxStyledTextCtrl_GetCaretSticky, 3371).
+-define(wxStyledTextCtrl_SetCaretSticky, 3372).
+-define(wxStyledTextCtrl_ToggleCaretSticky, 3373).
+-define(wxStyledTextCtrl_SetPasteConvertEndings, 3374).
+-define(wxStyledTextCtrl_GetPasteConvertEndings, 3375).
+-define(wxStyledTextCtrl_SelectionDuplicate, 3376).
+-define(wxStyledTextCtrl_SetCaretLineBackAlpha, 3377).
+-define(wxStyledTextCtrl_GetCaretLineBackAlpha, 3378).
+-define(wxStyledTextCtrl_StartRecord, 3379).
+-define(wxStyledTextCtrl_StopRecord, 3380).
+-define(wxStyledTextCtrl_SetLexer, 3381).
+-define(wxStyledTextCtrl_GetLexer, 3382).
+-define(wxStyledTextCtrl_Colourise, 3383).
+-define(wxStyledTextCtrl_SetProperty, 3384).
+-define(wxStyledTextCtrl_SetKeyWords, 3385).
+-define(wxStyledTextCtrl_SetLexerLanguage, 3386).
+-define(wxStyledTextCtrl_GetProperty, 3387).
+-define(wxStyledTextCtrl_GetStyleBitsNeeded, 3388).
+-define(wxStyledTextCtrl_GetCurrentLine, 3389).
+-define(wxStyledTextCtrl_StyleSetSpec, 3390).
+-define(wxStyledTextCtrl_StyleSetFont, 3391).
+-define(wxStyledTextCtrl_StyleSetFontAttr, 3392).
+-define(wxStyledTextCtrl_StyleSetCharacterSet, 3393).
+-define(wxStyledTextCtrl_StyleSetFontEncoding, 3394).
+-define(wxStyledTextCtrl_CmdKeyExecute, 3395).
+-define(wxStyledTextCtrl_SetMargins, 3396).
+-define(wxStyledTextCtrl_GetSelection, 3397).
+-define(wxStyledTextCtrl_PointFromPosition, 3398).
+-define(wxStyledTextCtrl_ScrollToLine, 3399).
+-define(wxStyledTextCtrl_ScrollToColumn, 3400).
+-define(wxStyledTextCtrl_SetVScrollBar, 3401).
+-define(wxStyledTextCtrl_SetHScrollBar, 3402).
+-define(wxStyledTextCtrl_GetLastKeydownProcessed, 3403).
+-define(wxStyledTextCtrl_SetLastKeydownProcessed, 3404).
+-define(wxStyledTextCtrl_SaveFile, 3405).
+-define(wxStyledTextCtrl_LoadFile, 3406).
+-define(wxStyledTextCtrl_DoDragOver, 3407).
+-define(wxStyledTextCtrl_DoDropText, 3408).
+-define(wxStyledTextCtrl_GetUseAntiAliasing, 3409).
+-define(wxStyledTextCtrl_AddTextRaw, 3410).
+-define(wxStyledTextCtrl_InsertTextRaw, 3411).
+-define(wxStyledTextCtrl_GetCurLineRaw, 3412).
+-define(wxStyledTextCtrl_GetLineRaw, 3413).
+-define(wxStyledTextCtrl_GetSelectedTextRaw, 3414).
+-define(wxStyledTextCtrl_GetTextRangeRaw, 3415).
+-define(wxStyledTextCtrl_SetTextRaw, 3416).
+-define(wxStyledTextCtrl_GetTextRaw, 3417).
+-define(wxStyledTextCtrl_AppendTextRaw, 3418).
+-define(wxArtProvider_GetBitmap, 3419).
+-define(wxArtProvider_GetIcon, 3420).
+-define(wxTreeEvent_GetKeyCode, 3421).
+-define(wxTreeEvent_GetItem, 3422).
+-define(wxTreeEvent_GetKeyEvent, 3423).
+-define(wxTreeEvent_GetLabel, 3424).
+-define(wxTreeEvent_GetOldItem, 3425).
+-define(wxTreeEvent_GetPoint, 3426).
+-define(wxTreeEvent_IsEditCancelled, 3427).
+-define(wxTreeEvent_SetToolTip, 3428).
+-define(wxNotebookEvent_GetOldSelection, 3429).
+-define(wxNotebookEvent_GetSelection, 3430).
+-define(wxNotebookEvent_SetOldSelection, 3431).
+-define(wxNotebookEvent_SetSelection, 3432).
+-define(wxFileDataObject_new, 3433).
+-define(wxFileDataObject_AddFile, 3434).
+-define(wxFileDataObject_GetFilenames, 3435).
+-define(wxFileDataObject_destroy, 3436).
+-define(wxTextDataObject_new, 3437).
+-define(wxTextDataObject_GetTextLength, 3438).
+-define(wxTextDataObject_GetText, 3439).
+-define(wxTextDataObject_SetText, 3440).
+-define(wxTextDataObject_destroy, 3441).
+-define(wxBitmapDataObject_new_1_1, 3442).
+-define(wxBitmapDataObject_new_1_0, 3443).
+-define(wxBitmapDataObject_GetBitmap, 3444).
+-define(wxBitmapDataObject_SetBitmap, 3445).
+-define(wxBitmapDataObject_destroy, 3446).
+-define(wxClipboard_new, 3448).
+-define(wxClipboard_destruct, 3449).
+-define(wxClipboard_AddData, 3450).
+-define(wxClipboard_Clear, 3451).
+-define(wxClipboard_Close, 3452).
+-define(wxClipboard_Flush, 3453).
+-define(wxClipboard_GetData, 3454).
+-define(wxClipboard_IsOpened, 3455).
+-define(wxClipboard_Open, 3456).
+-define(wxClipboard_SetData, 3457).
+-define(wxClipboard_UsePrimarySelection, 3459).
+-define(wxClipboard_IsSupported, 3460).
+-define(wxClipboard_Get, 3461).
+-define(wxSpinEvent_GetPosition, 3462).
+-define(wxSpinEvent_SetPosition, 3463).
+-define(wxSplitterWindow_new_0, 3464).
+-define(wxSplitterWindow_new_2, 3465).
+-define(wxSplitterWindow_destruct, 3466).
+-define(wxSplitterWindow_Create, 3467).
+-define(wxSplitterWindow_GetMinimumPaneSize, 3468).
+-define(wxSplitterWindow_GetSashGravity, 3469).
+-define(wxSplitterWindow_GetSashPosition, 3470).
+-define(wxSplitterWindow_GetSplitMode, 3471).
+-define(wxSplitterWindow_GetWindow1, 3472).
+-define(wxSplitterWindow_GetWindow2, 3473).
+-define(wxSplitterWindow_Initialize, 3474).
+-define(wxSplitterWindow_IsSplit, 3475).
+-define(wxSplitterWindow_ReplaceWindow, 3476).
+-define(wxSplitterWindow_SetSashGravity, 3477).
+-define(wxSplitterWindow_SetSashPosition, 3478).
+-define(wxSplitterWindow_SetSashSize, 3479).
+-define(wxSplitterWindow_SetMinimumPaneSize, 3480).
+-define(wxSplitterWindow_SetSplitMode, 3481).
+-define(wxSplitterWindow_SplitHorizontally, 3482).
+-define(wxSplitterWindow_SplitVertically, 3483).
+-define(wxSplitterWindow_Unsplit, 3484).
+-define(wxSplitterWindow_UpdateSize, 3485).
+-define(wxSplitterEvent_GetSashPosition, 3486).
+-define(wxSplitterEvent_GetX, 3487).
+-define(wxSplitterEvent_GetY, 3488).
+-define(wxSplitterEvent_GetWindowBeingRemoved, 3489).
+-define(wxSplitterEvent_SetSashPosition, 3490).
+-define(wxHtmlWindow_new_0, 3491).
+-define(wxHtmlWindow_new_2, 3492).
+-define(wxHtmlWindow_AppendToPage, 3493).
+-define(wxHtmlWindow_GetOpenedAnchor, 3494).
+-define(wxHtmlWindow_GetOpenedPage, 3495).
+-define(wxHtmlWindow_GetOpenedPageTitle, 3496).
+-define(wxHtmlWindow_GetRelatedFrame, 3497).
+-define(wxHtmlWindow_HistoryBack, 3498).
+-define(wxHtmlWindow_HistoryCanBack, 3499).
+-define(wxHtmlWindow_HistoryCanForward, 3500).
+-define(wxHtmlWindow_HistoryClear, 3501).
+-define(wxHtmlWindow_HistoryForward, 3502).
+-define(wxHtmlWindow_LoadFile, 3503).
+-define(wxHtmlWindow_LoadPage, 3504).
+-define(wxHtmlWindow_SelectAll, 3505).
+-define(wxHtmlWindow_SelectionToText, 3506).
+-define(wxHtmlWindow_SelectLine, 3507).
+-define(wxHtmlWindow_SelectWord, 3508).
+-define(wxHtmlWindow_SetBorders, 3509).
+-define(wxHtmlWindow_SetFonts, 3510).
+-define(wxHtmlWindow_SetPage, 3511).
+-define(wxHtmlWindow_SetRelatedFrame, 3512).
+-define(wxHtmlWindow_SetRelatedStatusBar, 3513).
+-define(wxHtmlWindow_ToText, 3514).
+-define(wxHtmlWindow_destroy, 3515).
+-define(wxHtmlLinkEvent_GetLinkInfo, 3516).
+-define(wxSystemSettings_GetColour, 3517).
+-define(wxSystemSettings_GetFont, 3518).
+-define(wxSystemSettings_GetMetric, 3519).
+-define(wxSystemSettings_GetScreenType, 3520).
+-define(wxSystemOptions_GetOption, 3521).
+-define(wxSystemOptions_GetOptionInt, 3522).
+-define(wxSystemOptions_HasOption, 3523).
+-define(wxSystemOptions_IsFalse, 3524).
+-define(wxSystemOptions_SetOption_2_1, 3525).
+-define(wxSystemOptions_SetOption_2_0, 3526).
+-define(wxAuiNotebookEvent_SetSelection, 3527).
+-define(wxAuiNotebookEvent_GetSelection, 3528).
+-define(wxAuiNotebookEvent_SetOldSelection, 3529).
+-define(wxAuiNotebookEvent_GetOldSelection, 3530).
+-define(wxAuiNotebookEvent_SetDragSource, 3531).
+-define(wxAuiNotebookEvent_GetDragSource, 3532).
+-define(wxAuiManagerEvent_SetManager, 3533).
+-define(wxAuiManagerEvent_GetManager, 3534).
+-define(wxAuiManagerEvent_SetPane, 3535).
+-define(wxAuiManagerEvent_GetPane, 3536).
+-define(wxAuiManagerEvent_SetButton, 3537).
+-define(wxAuiManagerEvent_GetButton, 3538).
+-define(wxAuiManagerEvent_SetDC, 3539).
+-define(wxAuiManagerEvent_GetDC, 3540).
+-define(wxAuiManagerEvent_Veto, 3541).
+-define(wxAuiManagerEvent_GetVeto, 3542).
+-define(wxAuiManagerEvent_SetCanVeto, 3543).
+-define(wxAuiManagerEvent_CanVeto, 3544).
+-define(wxLogNull_new, 3545).
+-define(wxLogNull_destroy, 3546).
+-define(wxTaskBarIcon_new, 3547).
+-define(wxTaskBarIcon_destruct, 3548).
+-define(wxTaskBarIcon_PopupMenu, 3549).
+-define(wxTaskBarIcon_RemoveIcon, 3550).
+-define(wxTaskBarIcon_SetIcon, 3551).
+-define(wxLocale_new_0, 3552).
+-define(wxLocale_new_2, 3554).
+-define(wxLocale_destruct, 3555).
+-define(wxLocale_Init, 3557).
+-define(wxLocale_AddCatalog_1, 3558).
+-define(wxLocale_AddCatalog_3, 3559).
+-define(wxLocale_AddCatalogLookupPathPrefix, 3560).
+-define(wxLocale_GetCanonicalName, 3561).
+-define(wxLocale_GetLanguage, 3562).
+-define(wxLocale_GetLanguageName, 3563).
+-define(wxLocale_GetLocale, 3564).
+-define(wxLocale_GetName, 3565).
+-define(wxLocale_GetString_2, 3566).
+-define(wxLocale_GetString_4, 3567).
+-define(wxLocale_GetHeaderValue, 3568).
+-define(wxLocale_GetSysName, 3569).
+-define(wxLocale_GetSystemEncoding, 3570).
+-define(wxLocale_GetSystemEncodingName, 3571).
+-define(wxLocale_GetSystemLanguage, 3572).
+-define(wxLocale_IsLoaded, 3573).
+-define(wxLocale_IsOk, 3574).
+-define(wxActivateEvent_GetActive, 3575).
+-define(wxPopupWindow_new_2, 3577).
+-define(wxPopupWindow_new_0, 3578).
+-define(wxPopupWindow_destruct, 3580).
+-define(wxPopupWindow_Create, 3581).
+-define(wxPopupWindow_Position, 3582).
+-define(wxPopupTransientWindow_new_0, 3583).
+-define(wxPopupTransientWindow_new_2, 3584).
+-define(wxPopupTransientWindow_destruct, 3585).
+-define(wxPopupTransientWindow_Popup, 3586).
+-define(wxPopupTransientWindow_Dismiss, 3587).
+-define(wxOverlay_new, 3588).
+-define(wxOverlay_destruct, 3589).
+-define(wxOverlay_Reset, 3590).
+-define(wxDCOverlay_new_6, 3591).
+-define(wxDCOverlay_new_2, 3592).
+-define(wxDCOverlay_destruct, 3593).
+-define(wxDCOverlay_Clear, 3594).
diff --git a/lib/wx/src/wxe_server.erl b/lib/wx/src/wxe_server.erl
index cc253b1143..ae9440f890 100644
--- a/lib/wx/src/wxe_server.erl
+++ b/lib/wx/src/wxe_server.erl
@@ -352,25 +352,8 @@ handle_disconnect(Object, Evh = #evh{cb=Fun}, From,
State0 = #state{users=Users0, cb=Callbacks}) ->
#user{events=Evs0} = gb_trees:get(From, Users0),
FunId = gb_trees:lookup(Fun, Callbacks),
- case find_handler(Evs0, Object, Evh#evh{cb=FunId}) of
- [] ->
- {reply, false, State0};
- Handlers ->
- case disconnect(Object,Handlers) of
- #evh{} -> {reply, true, State0};
- Result -> {reply, Result, State0}
- end
- end.
-
-disconnect(Object,[Ev|Evs]) ->
- try wxEvtHandler:disconnect_impl(Object,Ev) of
- true -> Ev;
- false -> disconnect(Object, Evs);
- Error -> Error
- catch _:_ ->
- false
- end;
-disconnect(_, []) -> false.
+ Handlers = find_handler(Evs0, Object, Evh#evh{cb=FunId}),
+ {reply, {try_in_order, Handlers}, State0}.
find_handler([{Object,Evh}|Evs], Object, Match) ->
case match_handler(Match, Evh) of
diff --git a/lib/wx/src/wxe_util.erl b/lib/wx/src/wxe_util.erl
index 1983e6783a..398ceddd4f 100644
--- a/lib/wx/src/wxe_util.erl
+++ b/lib/wx/src/wxe_util.erl
@@ -127,8 +127,21 @@ connect_cb(Object,EvData0 = #evh{cb=Callback}) ->
disconnect_cb(Object,EvData) ->
Server = (wx:get_env())#wx_env.sv,
- gen_server:call(Server, {disconnect_cb,Object,EvData}, infinity).
-
+ {try_in_order, Handlers} =
+ gen_server:call(Server, {disconnect_cb,Object,EvData}, infinity),
+ disconnect(Object, Handlers).
+
+disconnect(Object,[Ev|Evs]) ->
+ try wxEvtHandler:disconnect_impl(Object,Ev) of
+ true -> true;
+ false -> disconnect(Object, Evs);
+ Error -> Error
+ catch _:_ ->
+ false
+ end;
+disconnect(_, []) -> false.
+
+
debug_cast(1, Op, _Args, _Port) ->
check_previous(),
case ets:lookup(wx_debug_info,Op) of
diff --git a/lib/wx/test/wx_class_SUITE.erl b/lib/wx/test/wx_class_SUITE.erl
index 93a4c24a84..876db9893f 100644
--- a/lib/wx/test/wx_class_SUITE.erl
+++ b/lib/wx/test/wx_class_SUITE.erl
@@ -526,14 +526,19 @@ toolbar(Config) ->
Wx = wx:new(),
Frame = wxFrame:new(Wx, ?wxID_ANY, "Frame"),
TB = wxFrame:createToolBar(Frame),
- wxToolBar:addTool(TB, 747, "PressMe", wxArtProvider:getBitmap("wxART_COPY", [{size, {16,16}}]),
+ BM1 = wxArtProvider:getBitmap("wxART_COPY", [{size, {16,16}}, {client, "wxART_TOOLBAR"}]),
+ BM2 = wxArtProvider:getBitmap("wxART_TICK_MARK", [{size, {16,16}}, {client, "wxART_TOOLBAR"}]),
+ wxToolBar:addTool(TB, 747, "PressMe", BM1,
[{shortHelp, "Press Me"}]),
-
+ catch wxToolBar:addStretchableSpace(TB), %% wxWidgets 3.0 only
Add = fun(#wx{}, _) ->
- wxToolBar:addTool(TB, -1, "Added", wxArtProvider:getBitmap("wxART_TICK_MARK", [{size, {16,16}}]),
- [{shortHelp, "Test 2 popup text"}])
+ wxToolBar:addTool(TB, -1, "Added", BM2,
+ [{shortHelp, "Test 2 popup text"}]),
+ catch wxToolBar:addStretchableSpace(TB), %% wxWidgets 3.0 only
+ wxToolBar:realize(TB)
end,
+ wxToolBar:realize(TB),
wxFrame:connect(Frame, command_menu_selected, [{callback, Add}, {id, 747}]),
wxFrame:show(Frame),
wx_test_lib:wx_destroy(Frame,Config).
diff --git a/make/otp_release_targets.mk b/make/otp_release_targets.mk
index 97e9e4bb43..e104b68991 100644
--- a/make/otp_release_targets.mk
+++ b/make/otp_release_targets.mk
@@ -113,7 +113,16 @@ $(HTMLDIR)/$(APPLICATION).eix: $(XML_FILES) $(SPECS_FILES)
docs: $(HTMLDIR)/$(APPLICATION).eix
xmllint: $(XML_FILES)
- $(XMLLINT) --noout --valid --nodefdtd --loaddtd --path $(DOCGEN)/priv/dtd:$(DOCGEN)/priv/dtd_html_entities $(XML_FILES)
+ @echo "Running xmllint"
+ @BookFiles=`awk -F\" '/xi:include/ {print $$2}' book.xml`; \
+ for i in $$BookFiles; do \
+ if [ $$i = "notes.xml" ]; then \
+ echo Checking $$i; \
+ xmllint --noout --valid --nodefdtd --loaddtd --path $(DOCGEN)/priv/dtd:$(DOCGEN)/priv/dtd_html_entities $$i; \
+ else\
+ awk -F\" '/xi:include/ {print "echo Checking " $$2 ;print "xmllint --noout --valid --nodefdtd --loaddtd --path $(DOCGEN)/priv/dtd:$(DOCGEN)/priv/dtd_html_entities " $$2}' $$i |sh; \
+ fi \
+ done
# ----------------------------------------------------
# Local documentation target for testing
diff --git a/otp_versions.table b/otp_versions.table
index f68c7a60e7..587748895f 100644
--- a/otp_versions.table
+++ b/otp_versions.table
@@ -1,3 +1,5 @@
+OTP-18.1.5 : ssh-4.1.3 # asn1-4.0 common_test-1.11 compiler-6.0.1 cosEvent-2.2 cosEventDomain-1.2 cosFileTransfer-1.2 cosNotification-1.2 cosProperty-1.2 cosTime-1.2 cosTransactions-1.3 crypto-3.6.1 debugger-4.1.1 dialyzer-2.8.1 diameter-1.11 edoc-0.7.17 eldap-1.2 erl_docgen-0.4 erl_interface-3.8 erts-7.1 et-1.5.1 eunit-2.2.11 gs-1.6 hipe-3.13 ic-4.4 inets-6.0.3 jinterface-1.6 kernel-4.1 megaco-3.18 mnesia-4.13.2 observer-2.1 odbc-2.11.1 orber-3.8 os_mon-2.4 ose-1.1 otp_mibs-1.1 parsetools-2.1 percept-0.8.11 public_key-1.0.1 reltool-0.7 runtime_tools-1.9.1 sasl-2.6 snmp-5.2 ssl-7.1 stdlib-2.6 syntax_tools-1.7 test_server-3.9 tools-2.8.1 typer-0.9.9 webtool-0.9 wx-1.5 xmerl-1.3.8 :
+OTP-18.1.4 : inets-6.0.3 # asn1-4.0 common_test-1.11 compiler-6.0.1 cosEvent-2.2 cosEventDomain-1.2 cosFileTransfer-1.2 cosNotification-1.2 cosProperty-1.2 cosTime-1.2 cosTransactions-1.3 crypto-3.6.1 debugger-4.1.1 dialyzer-2.8.1 diameter-1.11 edoc-0.7.17 eldap-1.2 erl_docgen-0.4 erl_interface-3.8 erts-7.1 et-1.5.1 eunit-2.2.11 gs-1.6 hipe-3.13 ic-4.4 jinterface-1.6 kernel-4.1 megaco-3.18 mnesia-4.13.2 observer-2.1 odbc-2.11.1 orber-3.8 os_mon-2.4 ose-1.1 otp_mibs-1.1 parsetools-2.1 percept-0.8.11 public_key-1.0.1 reltool-0.7 runtime_tools-1.9.1 sasl-2.6 snmp-5.2 ssh-4.1.2 ssl-7.1 stdlib-2.6 syntax_tools-1.7 test_server-3.9 tools-2.8.1 typer-0.9.9 webtool-0.9 wx-1.5 xmerl-1.3.8 :
OTP-18.1.3 : ssh-4.1.2 # asn1-4.0 common_test-1.11 compiler-6.0.1 cosEvent-2.2 cosEventDomain-1.2 cosFileTransfer-1.2 cosNotification-1.2 cosProperty-1.2 cosTime-1.2 cosTransactions-1.3 crypto-3.6.1 debugger-4.1.1 dialyzer-2.8.1 diameter-1.11 edoc-0.7.17 eldap-1.2 erl_docgen-0.4 erl_interface-3.8 erts-7.1 et-1.5.1 eunit-2.2.11 gs-1.6 hipe-3.13 ic-4.4 inets-6.0.2 jinterface-1.6 kernel-4.1 megaco-3.18 mnesia-4.13.2 observer-2.1 odbc-2.11.1 orber-3.8 os_mon-2.4 ose-1.1 otp_mibs-1.1 parsetools-2.1 percept-0.8.11 public_key-1.0.1 reltool-0.7 runtime_tools-1.9.1 sasl-2.6 snmp-5.2 ssl-7.1 stdlib-2.6 syntax_tools-1.7 test_server-3.9 tools-2.8.1 typer-0.9.9 webtool-0.9 wx-1.5 xmerl-1.3.8 :
OTP-18.1.2 : ssh-4.1.1 # asn1-4.0 common_test-1.11 compiler-6.0.1 cosEvent-2.2 cosEventDomain-1.2 cosFileTransfer-1.2 cosNotification-1.2 cosProperty-1.2 cosTime-1.2 cosTransactions-1.3 crypto-3.6.1 debugger-4.1.1 dialyzer-2.8.1 diameter-1.11 edoc-0.7.17 eldap-1.2 erl_docgen-0.4 erl_interface-3.8 erts-7.1 et-1.5.1 eunit-2.2.11 gs-1.6 hipe-3.13 ic-4.4 inets-6.0.2 jinterface-1.6 kernel-4.1 megaco-3.18 mnesia-4.13.2 observer-2.1 odbc-2.11.1 orber-3.8 os_mon-2.4 ose-1.1 otp_mibs-1.1 parsetools-2.1 percept-0.8.11 public_key-1.0.1 reltool-0.7 runtime_tools-1.9.1 sasl-2.6 snmp-5.2 ssl-7.1 stdlib-2.6 syntax_tools-1.7 test_server-3.9 tools-2.8.1 typer-0.9.9 webtool-0.9 wx-1.5 xmerl-1.3.8 :
OTP-18.1.1 : inets-6.0.2 mnesia-4.13.2 # asn1-4.0 common_test-1.11 compiler-6.0.1 cosEvent-2.2 cosEventDomain-1.2 cosFileTransfer-1.2 cosNotification-1.2 cosProperty-1.2 cosTime-1.2 cosTransactions-1.3 crypto-3.6.1 debugger-4.1.1 dialyzer-2.8.1 diameter-1.11 edoc-0.7.17 eldap-1.2 erl_docgen-0.4 erl_interface-3.8 erts-7.1 et-1.5.1 eunit-2.2.11 gs-1.6 hipe-3.13 ic-4.4 jinterface-1.6 kernel-4.1 megaco-3.18 observer-2.1 odbc-2.11.1 orber-3.8 os_mon-2.4 ose-1.1 otp_mibs-1.1 parsetools-2.1 percept-0.8.11 public_key-1.0.1 reltool-0.7 runtime_tools-1.9.1 sasl-2.6 snmp-5.2 ssh-4.1 ssl-7.1 stdlib-2.6 syntax_tools-1.7 test_server-3.9 tools-2.8.1 typer-0.9.9 webtool-0.9 wx-1.5 xmerl-1.3.8 :
@@ -6,6 +8,8 @@ OTP-18.0.3 : erts-7.0.3 # asn1-4.0 common_test-1.11 compiler-6.0 cosEvent-2.2 co
OTP-18.0.2 : erts-7.0.2 runtime_tools-1.9.1 # asn1-4.0 common_test-1.11 compiler-6.0 cosEvent-2.2 cosEventDomain-1.2 cosFileTransfer-1.2 cosNotification-1.2 cosProperty-1.2 cosTime-1.2 cosTransactions-1.3 crypto-3.6 debugger-4.1 dialyzer-2.8 diameter-1.10 edoc-0.7.17 eldap-1.2 erl_docgen-0.4 erl_interface-3.8 et-1.5.1 eunit-2.2.10 gs-1.6 hipe-3.12 ic-4.4 inets-6.0 jinterface-1.6 kernel-4.0 megaco-3.18 mnesia-4.13 observer-2.1 odbc-2.11 orber-3.8 os_mon-2.4 ose-1.1 otp_mibs-1.1 parsetools-2.1 percept-0.8.11 public_key-1.0 reltool-0.7 sasl-2.5 snmp-5.2 ssh-4.0 ssl-7.0 stdlib-2.5 syntax_tools-1.7 test_server-3.9 tools-2.8 typer-0.9.9 webtool-0.9 wx-1.4 xmerl-1.3.8 :
OTP-18.0.1 : erts-7.0.1 # asn1-4.0 common_test-1.11 compiler-6.0 cosEvent-2.2 cosEventDomain-1.2 cosFileTransfer-1.2 cosNotification-1.2 cosProperty-1.2 cosTime-1.2 cosTransactions-1.3 crypto-3.6 debugger-4.1 dialyzer-2.8 diameter-1.10 edoc-0.7.17 eldap-1.2 erl_docgen-0.4 erl_interface-3.8 et-1.5.1 eunit-2.2.10 gs-1.6 hipe-3.12 ic-4.4 inets-6.0 jinterface-1.6 kernel-4.0 megaco-3.18 mnesia-4.13 observer-2.1 odbc-2.11 orber-3.8 os_mon-2.4 ose-1.1 otp_mibs-1.1 parsetools-2.1 percept-0.8.11 public_key-1.0 reltool-0.7 runtime_tools-1.9 sasl-2.5 snmp-5.2 ssh-4.0 ssl-7.0 stdlib-2.5 syntax_tools-1.7 test_server-3.9 tools-2.8 typer-0.9.9 webtool-0.9 wx-1.4 xmerl-1.3.8 :
OTP-18.0 : asn1-4.0 common_test-1.11 compiler-6.0 cosEvent-2.2 cosEventDomain-1.2 cosFileTransfer-1.2 cosNotification-1.2 cosProperty-1.2 cosTime-1.2 cosTransactions-1.3 crypto-3.6 debugger-4.1 dialyzer-2.8 diameter-1.10 edoc-0.7.17 eldap-1.2 erl_docgen-0.4 erl_interface-3.8 erts-7.0 et-1.5.1 eunit-2.2.10 gs-1.6 hipe-3.12 ic-4.4 inets-6.0 jinterface-1.6 kernel-4.0 megaco-3.18 mnesia-4.13 observer-2.1 odbc-2.11 orber-3.8 os_mon-2.4 ose-1.1 otp_mibs-1.1 parsetools-2.1 percept-0.8.11 public_key-1.0 reltool-0.7 runtime_tools-1.9 sasl-2.5 snmp-5.2 ssh-4.0 ssl-7.0 stdlib-2.5 syntax_tools-1.7 test_server-3.9 tools-2.8 typer-0.9.9 webtool-0.9 wx-1.4 xmerl-1.3.8 # :
+OTP-17.5.6.6 : erts-6.4.1.5 # asn1-3.0.4 common_test-1.10.1 compiler-5.0.4 cosEvent-2.1.15 cosEventDomain-1.1.14 cosFileTransfer-1.1.16 cosNotification-1.1.21 cosProperty-1.1.17 cosTime-1.1.14 cosTransactions-1.2.14 crypto-3.5 debugger-4.0.3.1 dialyzer-2.7.4 diameter-1.9.2.1 edoc-0.7.16 eldap-1.1.1 erl_docgen-0.3.7 erl_interface-3.7.20 et-1.5 eunit-2.2.9 gs-1.5.16 hipe-3.11.3 ic-4.3.6 inets-5.10.9 jinterface-1.5.12 kernel-3.2.0.1 megaco-3.17.3 mnesia-4.12.5 observer-2.0.4 odbc-2.10.22 orber-3.7.1 os_mon-2.3.1 ose-1.0.2 otp_mibs-1.0.10 parsetools-2.0.12 percept-0.8.10 public_key-0.23 reltool-0.6.6 runtime_tools-1.8.16.1 sasl-2.4.1 snmp-5.1.2 ssh-3.2.4 ssl-6.0.1.1 stdlib-2.4 syntax_tools-1.6.18 test_server-3.8.1 tools-2.7.2 typer-0.9.8 webtool-0.8.10 wx-1.3.3 xmerl-1.3.7 :
+OTP-17.5.6.5 : erts-6.4.1.4 kernel-3.2.0.1 ssl-6.0.1.1 # asn1-3.0.4 common_test-1.10.1 compiler-5.0.4 cosEvent-2.1.15 cosEventDomain-1.1.14 cosFileTransfer-1.1.16 cosNotification-1.1.21 cosProperty-1.1.17 cosTime-1.1.14 cosTransactions-1.2.14 crypto-3.5 debugger-4.0.3.1 dialyzer-2.7.4 diameter-1.9.2.1 edoc-0.7.16 eldap-1.1.1 erl_docgen-0.3.7 erl_interface-3.7.20 et-1.5 eunit-2.2.9 gs-1.5.16 hipe-3.11.3 ic-4.3.6 inets-5.10.9 jinterface-1.5.12 megaco-3.17.3 mnesia-4.12.5 observer-2.0.4 odbc-2.10.22 orber-3.7.1 os_mon-2.3.1 ose-1.0.2 otp_mibs-1.0.10 parsetools-2.0.12 percept-0.8.10 public_key-0.23 reltool-0.6.6 runtime_tools-1.8.16.1 sasl-2.4.1 snmp-5.1.2 ssh-3.2.4 stdlib-2.4 syntax_tools-1.6.18 test_server-3.8.1 tools-2.7.2 typer-0.9.8 webtool-0.8.10 wx-1.3.3 xmerl-1.3.7 :
OTP-17.5.6.4 : debugger-4.0.3.1 erts-6.4.1.3 # asn1-3.0.4 common_test-1.10.1 compiler-5.0.4 cosEvent-2.1.15 cosEventDomain-1.1.14 cosFileTransfer-1.1.16 cosNotification-1.1.21 cosProperty-1.1.17 cosTime-1.1.14 cosTransactions-1.2.14 crypto-3.5 dialyzer-2.7.4 diameter-1.9.2.1 edoc-0.7.16 eldap-1.1.1 erl_docgen-0.3.7 erl_interface-3.7.20 et-1.5 eunit-2.2.9 gs-1.5.16 hipe-3.11.3 ic-4.3.6 inets-5.10.9 jinterface-1.5.12 kernel-3.2 megaco-3.17.3 mnesia-4.12.5 observer-2.0.4 odbc-2.10.22 orber-3.7.1 os_mon-2.3.1 ose-1.0.2 otp_mibs-1.0.10 parsetools-2.0.12 percept-0.8.10 public_key-0.23 reltool-0.6.6 runtime_tools-1.8.16.1 sasl-2.4.1 snmp-5.1.2 ssh-3.2.4 ssl-6.0.1 stdlib-2.4 syntax_tools-1.6.18 test_server-3.8.1 tools-2.7.2 typer-0.9.8 webtool-0.8.10 wx-1.3.3 xmerl-1.3.7 :
OTP-17.5.6.3 : diameter-1.9.2.1 # asn1-3.0.4 common_test-1.10.1 compiler-5.0.4 cosEvent-2.1.15 cosEventDomain-1.1.14 cosFileTransfer-1.1.16 cosNotification-1.1.21 cosProperty-1.1.17 cosTime-1.1.14 cosTransactions-1.2.14 crypto-3.5 debugger-4.0.3 dialyzer-2.7.4 edoc-0.7.16 eldap-1.1.1 erl_docgen-0.3.7 erl_interface-3.7.20 erts-6.4.1.2 et-1.5 eunit-2.2.9 gs-1.5.16 hipe-3.11.3 ic-4.3.6 inets-5.10.9 jinterface-1.5.12 kernel-3.2 megaco-3.17.3 mnesia-4.12.5 observer-2.0.4 odbc-2.10.22 orber-3.7.1 os_mon-2.3.1 ose-1.0.2 otp_mibs-1.0.10 parsetools-2.0.12 percept-0.8.10 public_key-0.23 reltool-0.6.6 runtime_tools-1.8.16.1 sasl-2.4.1 snmp-5.1.2 ssh-3.2.4 ssl-6.0.1 stdlib-2.4 syntax_tools-1.6.18 test_server-3.8.1 tools-2.7.2 typer-0.9.8 webtool-0.8.10 wx-1.3.3 xmerl-1.3.7 :
OTP-17.5.6.2 : erts-6.4.1.2 runtime_tools-1.8.16.1 # asn1-3.0.4 common_test-1.10.1 compiler-5.0.4 cosEvent-2.1.15 cosEventDomain-1.1.14 cosFileTransfer-1.1.16 cosNotification-1.1.21 cosProperty-1.1.17 cosTime-1.1.14 cosTransactions-1.2.14 crypto-3.5 debugger-4.0.3 dialyzer-2.7.4 diameter-1.9.2 edoc-0.7.16 eldap-1.1.1 erl_docgen-0.3.7 erl_interface-3.7.20 et-1.5 eunit-2.2.9 gs-1.5.16 hipe-3.11.3 ic-4.3.6 inets-5.10.9 jinterface-1.5.12 kernel-3.2 megaco-3.17.3 mnesia-4.12.5 observer-2.0.4 odbc-2.10.22 orber-3.7.1 os_mon-2.3.1 ose-1.0.2 otp_mibs-1.0.10 parsetools-2.0.12 percept-0.8.10 public_key-0.23 reltool-0.6.6 sasl-2.4.1 snmp-5.1.2 ssh-3.2.4 ssl-6.0.1 stdlib-2.4 syntax_tools-1.6.18 test_server-3.8.1 tools-2.7.2 typer-0.9.8 webtool-0.8.10 wx-1.3.3 xmerl-1.3.7 :
diff --git a/system/doc/reference_manual/processes.xml b/system/doc/reference_manual/processes.xml
index 6755bd8be6..f656d0318e 100644
--- a/system/doc/reference_manual/processes.xml
+++ b/system/doc/reference_manual/processes.xml
@@ -100,11 +100,9 @@ spawn(Module, Name, Args) -> pid()
<item><c>exit(Reason)</c></item>
<item><c>erlang:error(Reason)</c></item>
<item><c>erlang:error(Reason, Args)</c></item>
- <item><c>erlang:fault(Reason)</c></item>
- <item><c>erlang:fault(Reason, Args)</c></item>
</list>
<p>The process then terminates with reason <c>Reason</c> for
- <c>exit/1</c> or <c>{Reason,Stack} for the others</c>.</p>
+ <c>exit/1</c> or <c>{Reason,Stack}</c> for the others.</p>
<p>A process can also be terminated if it receives an exit signal
with another exit reason than <c>normal</c>, see
<seealso marker="#errors">Error Handling</seealso>.</p>
diff --git a/system/doc/reference_manual/typespec.xml b/system/doc/reference_manual/typespec.xml
index 7891f3a6b9..a238e3135a 100644
--- a/system/doc/reference_manual/typespec.xml
+++ b/system/doc/reference_manual/typespec.xml
@@ -197,6 +197,9 @@
<cell><c>char()</c></cell><cell><c>0..16#10ffff</c></cell>
</row>
<row>
+ <cell><c>nil()</c></cell><cell><c>[]</c></cell>
+ </row>
+ <row>
<cell><c>number()</c></cell><cell><c>integer() | float()</c></cell>
</row>
<row>
@@ -312,7 +315,7 @@
<p>
As seen, the basic syntax of a type is an atom followed by closed
parentheses. New types are declared using <c>-type</c> and <c>-opaque</c>
- compiler attributes as in the following:
+ attributes as in the following:
</p>
<pre>
-type my_struct_type() :: Type.
@@ -435,8 +438,8 @@
<section>
<title>Specifications for Functions</title>
<p>
- A specification (or contract) for a function is given using the new
- compiler attribute <c>-spec</c>. The general format is as follows:
+ A specification (or contract) for a function is given using the
+ <c>-spec</c> attribute. The general format is as follows:
</p>
<pre>
-spec Module:Function(ArgType1, ..., ArgTypeN) -> ReturnType.</pre>
@@ -451,7 +454,7 @@
explicitly) import these functions.
</p>
<p>
- Within a given module, the following shorthand suffice in most cases:
+ Within a given module, the following shorthand suffices in most cases:
</p>
<pre>
-spec Function(ArgType1, ..., ArgTypeN) -> ReturnType.</pre>
@@ -492,7 +495,8 @@
</p>
<pre> -spec id(X) -> X when X :: tuple().</pre>
<p>
- Currently, the <c>::</c> constraint (read as <c>is_subtype</c>) is
+ Currently, the <c>::</c> constraint
+ (read as &laquo;is a subtype of&raquo;) is
the only guard constraint that can be used in the <c>'when'</c>
part of a <c>'-spec'</c> attribute.
</p>
@@ -526,16 +530,6 @@
<pre>
-spec foo({X, integer()}) -> X when X :: atom()
; ([Y]) -> Y when Y :: number().</pre>
- <note>
- <p>
- For backwards compatibility the following form is also allowed:
- </p>
- <pre> -spec id(X) -> X when is_subtype(X, tuple()).</pre>
- <p>
- but its use is discouraged. It will be removed in a future
- Erlang/OTP release.
- </p>
- </note>
<p>
Some functions in Erlang are not meant to return;
either because they define servers or because they are used to